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

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

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

处理过程简介

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

1.      处理事实数据

处理事实数据简单的说就是将数据从数据源搬到分区对象的过程,因为分区中的事实数据需要关联到维度,所以中间还有一步是查找与事实数据对应的已经处理的维度键值。下面三步并行执行已完成事实处理:

  1. 发送SQL查询来从源中抽取数据,好像是每次10万行
  2. 为上面读入的1万行数据在分析服务的维度对象中查找响应的维度键值,然后填充到处理缓存中
  3. 当处理缓存满的时候,将数据写入到磁盘中

2.      构建聚合及位图索引

在事实数据被处理到分区对象之后,处理就开始构建聚合及位图索引。聚合的处理是在内存中进行的,如果内存不足以构建所有的聚合,那么就会一块一块的先写入到磁盘的临时文件,在处理的最后做合并。

在设计OLAP数据库的时候我们应该在聚合上做均衡的考虑,因为大量的聚合肯定会提高查询的效率,但是同时会降低处理的效率。

分区的处理是通过向OLAP数据库发出分区处理命令进行的,主要有以下的分区处理命令:

ProcessFull

全处理会首先删除现有的存储内容(事实数据、聚合及位图索引),然后首先执行ProcessData过程,紧接着执行ProcessIndexes

ProcessData

处理数据命令也是首先删除现有的存储内容(事实数据、聚合及位图索引),然后处理事实数据,但是不会构建聚合及位图索引

ProcessIndexes

该命令执行的时候假设事实数据已经存在了,它在事实数据上构建新的聚集及位图索引

ProcessAdd

该命令创建一个临时分区,在其上执行完全执行,最后将临时分区Merge到目标分区中。该命令式一个XMLA命令,在UI上名为ProcessIncremental

ProcessClear

删除分区中现有的存储内容,它是XMLA的命令,在UI上名为UnProcess

ProcessClear Indexes

仅删除分区中的聚合及位图索引

处理过程的监控

我们可以使用SQL Server自带的Profiler来对OLAP数据库的处理做监控,首先我们需要知道Profiler中哪些Events是用来监控OLAP处理的,其实这个问题比较显而易见,所有与之相关的事件都处于Process Reports这个目录下面,包括:

  • 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来降低数据库锁开销
  • 事实表的设计遵循以下的最优设计
Surrogatekeys tinyint, smallint, int, bigint
Datekey int inthe format yyyyMMdd
Integermeasures tinyint, 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端优化

待续….

处理选项的优化

待续….

时间: 2024-10-08 14:13:26

OALP数据库优化之2 – Cube处理优化的相关文章

【SQL server初级】数据库性能优化三:程序操作优化

数据库优化包含以下三部分,数据库自身的优化,数据库表优化,程序操作优化.此文为第三部分 数据库性能优化三:程序操作优化 概述:程序访问优化也可以认为是访问SQL语句的优化,一个好的SQL语句是可以减少非常多的程序性能的,下面列出常用错误习惯,并且提出相应的解决方案 一.操作符优化 1. IN.NOT IN 操作符 IN和EXISTS 性能有外表和内表区分的,但是在大数据量的表中推荐用EXISTS 代替IN . Not IN 不走索引的是绝对不能用的,可以用NOT EXISTS 代替 2. IS 

公交车路线查询系统后台数据库设计--换乘算法改进与优化

在<查询算法>一文中已经实现了换乘算法,但是,使用存储过程InquiryT2查询从“东圃镇”到“车陂路口”的乘车路线时,发现居然用了5分钟才查找出结果,这样的效率显然不适合实际应用.因此,有必要对原有的换乘算法进行优化和改进.在本文中,将给出一种改进的换乘算法,相比原有的算法,改进后的算法功能更强,效率更优. 1. “压缩”RouteT0 假设RouteT0有以下几行 如下图所示,当查询S1到S4的二次换乘路线时,将会产生3×2×4=24个结果 从图中可以看出,第1段路线中的3条线路的起点和站

数据库性能优化三:程序操作优化

数据库优化包含以下三部分,数据库自身的优化,数据库表优化,程序操作优化.此文为第三部分 数据库性能优化三:程序操作优化 概述:程序访问优化也可以认为是访问SQL语句的优化,一个好的SQL语句是可以减少非常多的程序性能的,下面列出常用错误习惯,并且提出相应的解决方案 一.操作符优化 1. IN.NOT IN 操作符 IN和EXISTS 性能有外表和内表区分的,但是在大数据量的表中推荐用EXISTS 代替IN . Not IN 不走索引的是绝对不能用的,可以用NOT EXISTS 代替 2. IS 

深入理解图优化与g2o:图优化篇

前言 本节我们将深入介绍视觉slam中的主流优化方法——图优化(graph-based optimization).下一节中,介绍一下非常流行的图优化库:g2o. 关于g2o,我13年写过一个文档,然而随着自己理解的加深,越发感觉不满意.本着对读者更负责任的精神,本文给大家重新讲一遍图优化和g2o.除了这篇文档,读者还可以找到一篇关于图优化的博客: http://blog.csdn.net/heyijia0327 那篇文章有作者介绍的一个简单案例,而本文则更注重对图优化和g2o的理解与评注. 本

根据自己的需要,把别人开发好的东西搬过来,优化and重构,在优化的过程中,甚至也会弄出一套全新的东西(转)

赵海平在今年三月份来到阿里,听毕玄(他现任主管)说去年五六月份就跟赵海平聊上了.有人问:为啥 BAT 三大巨头,你看中了阿里巴巴?在今天现场达一千多人的分享中赵海平给出了回复:“因为百度和腾讯没找我呗~”,他笑道,“百度以搜索为核心,优化了很多年了,估计也没啥可以优化的了:而腾讯除了 QQ 和微信,也没什么大型应用(别跟人家说哦)”.这不是原话哈,赵海平还是相当谦虚并且能言的,思维很开阔,两个小时的分享内容丰富,时不时还插两个故事,起初进场的手机和电脑都很自觉的收起来了~旁边的同事侃道:“高 P

《Java程序性能优化》学习笔记 Ⅰ设计优化

豆瓣读书:http://book.douban.com/subject/19969386/ 第一章 Java性能调优概述 1.性能的参考指标 执行时间: CPU时间: 内存分配: 磁盘吞吐量: 网络吞吐量: 响应时间: 2.木桶定律   系统的最终性能取决于系统中性能表现最差的组件,例如window系统内置的评分就是选取最低分.可能成为系统瓶颈的计算资源如,磁盘I/O,异常,数据库,锁竞争,内存等. 性能优化的几个方面,如设计优化,Java程序优化,并行程序开发及优化,JVM调优,Java性能调

网站推广优化(SEO,网站关键字优化,怎么优化网站,如何优化网站关键字)

网站推广优化教程100条(完整版)下面介绍新手建站推广完美教程,各位根据自己的实际情况酌情选用: 1.准备个好域名.①.尽量在5位数内,当然也不一定,反正要让用户好记.(看个人):②.尽量用顶级的域名,搜索排名感觉好一点.③.做中文站最好用拼音注册,不要问为什么.看百度(baidu.com)就是很好证明.④.域名的安全性,最好选择有些权威的注册商.⑤.好域名或者说主域名最好注册3年以上,因为百度在扒正规站的毛的时候,会看这些资料,他会觉得你不会很快转行的…… 2.网站空间很重要①.速度打开速度慢

后端系统性能优化(第一季 3 sql优化)

昨天的博文介绍了如何去发现坏代码,如何优雅的去实现一个应用内的监控程序. 博文地址:后端系统性能优化(第一季 2 找出坏代码) 当然发现了坏代码之后,我们还是要想办法来改掉它,也许它会很顽固.今天说说性能优化的一个非常重要的部分:sql的优化 今天要说的不是怎么来写优秀的,性能好的sql,这些DBA们会比我更加专业.在我们公司,凡是DBA能优化的sql,DBA都在内部消化了,需要反馈给我们的,说明他们可能也束手无策.也是我们该出手的时候了. insert,update这类型的sql,性能一般不会

mysql优化-优化入门之MySQL的优化介绍及执行步骤

优化到底优化什么?      优化,一直是面试最常问的一个问题.因为从优化的角度,优化的思路,完全可以看出一个人的技术积累.那么,关于系统优化,假设这么个场景,用户反映系统太卡(其实就是高并发),那么我们怎么优化?如果请求过多,判定web服务器的压力过大,增加前端的web服务器,做负载均衡,如果请求静态界面不卡了,但是动态数据还是卡,说明MySQL处理的请求太多了,在应用层增加缓存.数据库层其实是最脆弱的一层,一般在应用设计时在上游就需要把请求拦截掉,数据库层只承担"能力范围内"的访问