您的位置:首页 > 博客中心 > 数据库 >

OALP数据库优化之2 – Cube处理优化

时间:2022-03-14 00:49

OALP数据库优化之2 – Cube处理优化

当我们在OLAP数据库的世界中说起Process的时候,它至少可以分为两类:维度的处理跟Cube的处理,本部分只讨论cube的处理及优化,维度的处理优化会在另一部分讨论。

首先我们应该明确所谓处理(Process)这个概念,它可以简单的理解为将数据从一个或多个数据源加载、搬移到分析服务对象中的过程,对Cube处理来说就是加载到度量值组分区中的过程,所以Cube处理的优化其实归根结底是分区的处理优化。

处理过程简介

如下图所示,分区的处理过程可以分为两步:

  • Process Report Begin

  • 事件ID为5,它表示所有OLAP数据库相关的处理报告的开始事件

    • Process Report Current

    事件ID为7,它表示所有进度报告当前状态事件。例如,在处理期间,当前报表包含有关被处理的对象(维度、分区、多维数据集等)的处理信息

    • Process Report End

    事件ID为6,它表示所有OLAP数据库相关的处理报告的开始事件

    • Process Report Error

    事件ID为8,它表示所有处理报告错误事件

    从我个人的使用情况来说,我一般只使用Process ReportEnd事件,因为所有的事件都是以Begin开始,中间经历Current最后以End或Error结束。因为我使用Profiler只是用来调优而不是找错,所以不需要Error事件;而任何出现在ProcessReport Begin的事件肯定最后会反应在Process Report End事件中(应该是这样的吧?),所以ProcessReport Begin和Process Report End之间我们只需要Process Report End就可以了;对于ProcessReport  Current,本人不是太明白这个事件是干什么的,不过它有一个其他事件无法代替的作用:假如度量值组有1千万数据,AS肯定是没办反一次性都读入内存然后处理的,所以它会每次读取比如10万数据来处理,然后再处理10万直至全部处理完,ProcessReport Current能捕获到现在为止处理的数据行数。

    接下来我们要知道的是关于Profiler捕获到的数据都有哪些信息,说白了就是有哪些数据列。我们在此只列出最主要的数据列:

    • EventSubClass– OLAP数据库处理事件类,下面是一些主要的事件

    • Process

    • Merge

    • Delete

    • DeleteOldAggregations

    • Rebuild

    • Commit

    • Rollback

    • CreateIndexes

    • CreateTable

    • InsertInto

    • Transaction

    • Initialize

    • Discretize

    • Query

    • CreateView

    • WriteData

    • ReadData

    • GroupData

    • GroupDataRecord

    • BuildIndex

    • Aggregate

    • BuildDecode

    • WriteDecode

    • BuildDMDecode

    • ExecuteSQL

    • NowExecutingSQL

    • ExecuteModifiedSQL

    • Connecting

    • BuildAggsAndIndexes

    • MergeAggsOnDisk

    • BuildIndexForRigidAggs

    • BuildIndexForFlexibleAggs

    • WriteAggsAndIndexes

    • WriteSegment

    • DataMiningProgress

    • ReadBufferFullReport

    • ProactiveCacheConversion

    • Backup

    • Restore

    • Synchronize

    • TextData– 与事件相关的文本数据,大部分情况下是对事件的一种描述。比如对于Process事件在结束时会描述为“Finishedprocessing the XXX partition”

    • DatabaseName– 事件发生的数据库

    • ObjectName& ObjectPath 表示事件发生的对象以及该对象的路径

    • StartTime– 事件开始时间

    • Duration- 包含所报告的事件开始到结束的时间长度(只存在于ProcessReport End事件中)

    • EndTime- 包含所报告事件的结束时间(只存在于ProcessReport End事件中)

    • IntegerData– 包含与发生的事件关联的整形数据,例如已处理行数的当前计数(只存在于ProcessReport End和Process Report Current事件中)

    •  

    下面我们以实际的例子来描述一下Profiler到底捕获了什么样的处理数据。对一个只有一个度量值组一个分区的Cube进行处理,Profiler捕获的事件如下:

    BuildProcessing Schedule

    Cube ProcessBegin

                    Measure Group Process Begin

                                    PartitionProcess Begin

                                                    WriteData for Partition Begin

                                                                    ExecuteSQL to get data from Source

                                                                    ReadData Begin

                                                                                    ReadData Current – 到现在为止处理的数据行

                                                                                    ReadData Current – 到现在为止处理的数据行

                                                                    ReadData End

                                                    WriteData for Partition End

                                                    BuildAggregation and Indexes Begin

                                                                    BuildIndex

                                                                    BuildAggregate

                                                    BuildAggregation and Indexes End

                                    PartitionProcess End

                    Measure Group Process End

    Cube ProcessEnd

    处理过程的优化

    毋庸置疑地有繁多的优化措施可以帮助我们提升Cube的处理效率,比如通过添加索引提升取元数据的速度,提升IO子系统,排除数据库锁等,但是在我们试图应用这些细的优化措施之前,我们应该首先确保我们应用了对Cube处理作用最大的技术:分区+增量处理。

     

    毋庸置疑地有繁多的优化措施可以帮助我们提升Cube的处理效率,比如通过添加索引提升取元数据的速度,提升IO子系统,排除数据库锁等,但是在我们试图应用这些细的优化措施之前,我们应该首先确保我们应用了对Cube处理作用最大的技术:分区+ 分区合并+ 增量处理

    恰当的分区是提升查询机处理效率最有效的方式,假如我们一个销售事实表中包含了近10年的近亿数据,并且还在以每天几万条数据的方式在增长,那如果该度量值组只有一个分区,我们每天不得不对该度量值组做FullProcess,也就是每天都需要处理上亿的数据;但是如果我们是一天一个分区,那么我们每天只需要处理几万数据就可以了。所以分区让我们可以将历史的、固定不变的数据与最近的数据隔离开来,这样就只需要处理最近的少量数据就可以了。

    不过实际中每天一个分区会造成管理的混乱,所以有时候我们可以只创建少量的分区,比如只有两个分区,一个表示历史分区,一个表示当前月数据的分区,这样每天我们只在当前月分区上做增量处理(给只处理一天的数据差不多,只是多了Merge的花费),然后在下月的第一天我们将当前月分区的数据Merge到历史分区中。

    如果每天的数据量不是特别大(比如千万甚至上亿),该方式能够满足绝大部分的处理性能需求。

     

    毋庸置疑地有繁多的优化措施可以帮助我们提升Cube的处理效率,比如通过添加索引提升取元数据的速度,提升IO子系统,排除数据库锁等,但是在我们试图应用这些细的优化措施之前,我们应该首先确保我们应用了对Cube处理作用最大的技术:分区+ 分区合并+ 增量处理

    恰当的分区是提升查询机处理效率最有效的方式,假如我们一个销售事实表中包含了近10年的近亿数据,并且还在以每天几万条数据的方式在增长,那如果该度量值组只有一个分区,我们每天不得不对该度量值组做FullProcess,也就是每天都需要处理上亿的数据;但是如果我们是一天一个分区,那么我们每天只需要处理几万数据就可以了。所以分区让我们可以将历史的、固定不变的数据与最近的数据隔离开来,这样就只需要处理最近的少量数据就可以了。

    不过实际中每天一个分区会造成管理的混乱,所以有时候我们可以只创建少量的分区,比如只有两个分区,一个表示历史分区,一个表示当前月数据的分区,这样每天我们只在当前月分区上做增量处理(给只处理一天的数据差不多,只是多了Merge的花费),然后在下月的第一天我们将当前月分区的数据Merge到历史分区中。

    如果每天的数据量不是特别大(比如千万甚至上亿),该方式能够满足绝大部分的处理性能需求。

    如果应用了上面简单的处理方式后还不能满足处理性能的要求,那么我们可能需要参考下面一些比较琐碎的优化方式:

    源数据端的优化

    所谓数据源端的优化其实就是关系型数据库的优化以及OLAP分区所对应的数据查询语句的优化,这主要有以下的方式:

    • 如果可能的话为分区查询语句构建恰当的索引,不过我们必须同时考虑到索引对数据插入的负面影响

    • 是每个度量值组的分区对应于至多一个关系型数据库表的分区,这样每个分区的数据查询语句只会访问一个表分区

    • 尽量从分区的数据查询语句中去除JOIN,被JOIN得出的列应该被物理化到事实表中

    • 如果有页面切分,我们可以重构索引来提升填充因子,同时可以采用数据压缩来降低IO

    • 通过使用NOLOCK来降低数据库锁开销

    • 事实表的设计遵循以下的最优设计

    Surrogatekeystinyint, smallint, int, bigint
    Datekeyint inthe format yyyyMMdd
    Integermeasurestinyint, smallint, int, bigint 
    Numericmeasures

    smallmoney, money, real, float

    (Note that decimaland vardecimal require more CPUpower to process than money and float types)
    Distinctcount columns

    tinyint, smallint, int, bigint

    (If your count column is char, consider either hashing or replacing with surrogate key)



    OLAP端优化

    待续….

    处理选项的优化

    待续….

     


    热门排行

    今日推荐

    热门手游