【.com快译】联机分析处理(OLAP)需要即时响应,因此其性能至关重要。虽然它的结构比较简单,但是在处理各种大型数据立方体时涉及到大量的计算。多维分析,通常称为OLAP(联机分析处理),是一种交互式数据分析过程,包括:数据立方体的旋转、切片和切块以及钻取。取(drill-down)等进行操作。其后端的计算结构比较简单,如下SQL语句所示。SELECTD,...,SUM(M),...FROMCWHERED'=d'AND...GROUPBYD,...该语句通过多个维度聚合各种度量。其中C是数据立方体,D,...代表选定的维度,M,...代表用于聚合的单个度量。除了SUM,我们还可以使用其他聚合函数。D'是切片维度。块操作的范围标准由语句DIN(d,...)表示。我们也可以在metric中定义一个规则,使用WHERE语句来选取一定范围内的值。OLAP分析需要即时响应,因此高性能至关重要。虽然这条语句的结构比较简单,但是当我们处理各种大数据立方体的时候,可能会涉及到很多的计算。在我们找到优化它们的方法之前,分析过程通常很慢。下面我们列出了几种常见的提高多维分析后端性能的方法。1.预聚合(Pre-Aggregation)早期的OLAP产品通常使用预聚合作为一种有效交换存储开销的方法。该方法通过部分或全部维度(在GROUPBY语句中定义)预先计算聚合值(在SELECT查询的各种指标中定义),并存储它们。这些中间结果可以直接被后面的计算使用,或者产生一些新的计算。这样,性能可以得到很大的提升。这些聚合的结果会占用大量空间。通常,可能有几十个维度,每个维度的值都在一位到两位数之间。简单的数学表明:预聚合的结果会比原始数据立方体大几倍到几十倍(即:如果考虑各种类型的聚合函数,比例为(k1+1)*(k2+1)*...至k1*k2*...)。虽然数据立方体不会太大而无法获得即时响应,但要做到数据量增加几十倍还是不可能的。一个折衷方案是只计算其中一些维度的聚合值。由于只有少数分组维度(在GROUPBY语句中定义)将暴露在OLAP接口中,因此我们可以在m维度上进行聚合。如果m的值不大于5,存储开销会在一个合理的范围内,大部分用户操作都会得到快速响应。当然,不能使用其他维度的切片标准来处理部分聚合。然而,钻孔恰好是基于切片的。这严重导致即使是那些广泛使用的聚合(在多维分析中并不少见)也不能对特定切片标准(例如,获得超过¥1000的销售额)使用相同的度量。因此,聚合函数可能只包含一个条件(例如,总成本低于¥100)。可以看出,预聚合结果对于所有这些场景都是无用的。预聚合只能处理一些最常见的场景,这些场景仅代表所有类型的多维分析场景的一小部分。大部分场景还是使用全遍历。2.基于分段的并行处理(Segment-BasedParallelProcessing)多维分析本质上就是对数据进行过滤和分组,从而很容易实现并行处理。其步骤包括:将数据分成多个段,分别处理,收集那些独立的子任务处理的结果进行聚合。无论是在单机上,还是在多节点集群上,甚至是两者结合,其多线程处理实现起来都不难。虽然多维分析的结果是可视化的,但我们肉眼所能看到的数据,远远少于现代计算机内存所能存储的数据。对于足够小的数据集,它可以很容易地加载到内存中,而无需在内存和磁盘之间进行交换。它的编程也比较简单,性能也很出色。但是,一个计算过程中产生的大数据集,直接提交到接口,它的计算立即暂停。根据我们的测试,如果由同一个多线程处理的所有子任务将它们的结果合并到同一个结果集中,由于多个线程使用单个资源进行同步操作,其性能可能会受到严重影响。影响。可以看出,通过使用共享的最终数据集,内存使用量将减少。更多的线程并不总是更好,当线程超过CPU核心数时它就变得无效了。对于存储在外部存储设备上的数据,需要进行测试以获得多线程处理的真实结果。因为硬盘的并发能力(通常小于CPU核数),需要考虑。根据每段末尾的记录数和标记数,很容易划分静态数据。但是如果要对动态数据进行均分,就比较麻烦了。本文将在下面更详细地讨论。对于单个计算任务,并行处理可以带来成倍的性能提升。并且由于OLAP的操作基本上是并发事务,当用户数量较少时,它的性能提升可能会被抵消。所以我们需要一个更好的方法。3.排序索引(SortedIndex)由于非切片聚合操作总是涉及到整体的数据立方体,我们很难通过进行预聚合来减少计算量。但是对于切片操作(钻取),如果数据立方体已经排序,则不需要进行全遍历。如果我们能为D维度创建一个索引,就意味着它的值与对应的序号记录相关联,形成了一定的顺序。那么我们就可以快速定位到D维中包含的满足切片条件的记录。这是一个简单的二分查找。不需要全量遍历所有数据,计算量可以减少几个数量级(这也取决于D的取值范围)。理论上,我们可以为每个维度创建一个索引,因为它并不昂贵。而当涉及到相应的切片时,其性能会得到很大的提升。然而,包含D1和D2维度的多字段索引在实践中很少使用。因为它不能快速定位只包含D2维度的切片,所以它只对同时包含D1和D2的切片非常有效。定位并记录包含最大值范围的维度切片后,大量的计算量将相应减少。当然,我们也可以通过维度来遍历其他切片。不幸的是,这种原始方法仅适用于允许频繁、小规模访问的内存数据。在大多数情况下,我们要处理的数据集都相当大,需要存储在磁盘上。但是即使通过索引,检索大量无序记录的操作对性能的提升影响不大。只有真正对数据进行了排序,并且切片中的记录是连续存储的,其性能才会有明显的提升。由于需要根据特定维度的排序目的来复制各种数据,所以成本还是比较高的。有一种解决方案可以创建两个数据副本:一个数据按D1,...,Dn维度排序,另一个数据按Dn,...,D1维度排序。得到的数据量只有两倍大,还是可以接受的。通过这个二维序列,有一个切片维度总是从头开始降序排列,保证了这个维度的切片数据在整体上是连续的,从而达到更好的性能提升。4.压缩列存储(CompressedColumnStorage)多维分析的一个强大工具是:列存储。通常,我们在对数据立方体进行多维分析时,会有大量的字段(维度和度量),少则几十,多则数百。但是真正有用的并不多。如果不考虑切片维度,通常只有5个或更少。由于可以对切片进行索引处理,因此只需要遍历很少的几个字段。基于这样的考虑,列式存储正好可以发挥其优势。在外存的计算中,I/O操作是非常耗时的。因此,减少要检索的数据以提高性能比减少计算次数更有意义。比如一个有100个字段的数据立方体,如果只检索5个字段,它的I/O消耗会下降到20倍,这会导致性能飙升几个数量级。列式存储的另一个优点是它支持数据压缩。在对数据的D1,...,Dn维度进行排序存储时,发现D1在一系列记录中具有相同的值;D2在较不连续的记录中具有相同的值;以此类推,在越来越少的连续记录中,就会出现这样相同的值;直到Dn中几乎没有这种连续性。考虑到我们不需要存储那些重复的连续相同的值,我们可以一次存储它们并记录它们的数量。通过以这种方式减少数据足迹,我们可以减少对外部存储的I/O访问并提高性能。在使用列式存储时,我们还需要考虑以下问题。由于列式存储并不能减少计算量,所以对于内存中的数据操作帮助不大。但是其压缩存储方案可以有效降低内存消耗。列式存储使基于段的并行处理和索引创建变得复杂。列拆分需要相互一致,索引需要同时准确引用所有列。而且在使用压缩列存储的时候,会比较麻烦。尽管有这些麻烦的问题,但一般来说,静态数据使用列式存储并不太困难(只是不要忘记处理它们)。使用列式存储会增加并发压力的风险。当字段总数不多或者我们需要检索的字段太多时,它就失去了优势。通过硬盘额外使用并行处理会进一步增加并发压力,也可能导致性能下降。因此,能够更好地支持并发的SSD会更合适。原标题:提高多维数据分析的4种方法作者:姜步兴
