Power BI 性能提升解决方案


2022年6月20日上午9点31分| Mike Wu | 1347

一、选择合适的连接方式

1.在将Power BI 与数据源连接时,若对数据的实时性要求不高,尽量选用Import连接方式,而不是Direct,Import连接是将数据加载到内存中计算,属于性能最好的连接方式。

如下,在一个510条数据量的简单模型里,Direct连接方式的平均计算时间为3.3秒,而Import连接方式的平均计算时间仅0.26秒,两者性能相差近12倍。

website/blog/editor/media-7m7si04l.png

website/blog/editor/media-ppw7i70c.png

二、减少数据量级

1.减少无关列,对于BI模型不需要使用到的列,可以在PQ中删除,或者在SQL中筛除,以减少模型的大小。

2.减少无效数据行,如:一些财务报表中,只涉及到金额求和,求百分比类的统计,那对于金额为0或者为空的行是无效的,可筛除这些无效行;一些公司的数据库中存储了很多年的数据,但在BI模型内只使用到了近2年的数据,便可将近2年之外的其它数据筛除。

3.聚合粒度,对于只需要统计粒度较粗的模型,可以按照相应的统计粒度提取聚合数据,不必将最细粒度的明细数据全部加载到BI模型内。例如,最细粒度只统计到订单头ID,再导入数据前,可前按照订单头ID聚合数据后导入,而不是将订单行的所有明细数据导入。

三、优化模型结构

1.尽量使用星型结构

星型结构为,一张事实表被多张维度表所关联,每张维度表都对应一个主题,有一个主键列,而其它列则是围绕主键列的属性说明。维度表中的主键与事实表中的外键关联,关系为一对多,单向筛选,只能用维度表的列去筛选事实表的数据,而不能用事实表筛选维度表。

例如,DimProduct维度表,主键为ProductKey,其它列则为对应的属性,如:产品名称,颜色,尺寸,所属品类,品牌等。

website/blog/editor/media-sxu9ieum.png

在实际的业务场景中,往往模型中不会只有单张事实表,而是有多张事实表,多张维度表,此时一般采用的是星型模型衍生出来的星座模型,即多张事实表共用维度表,一张维度表与多张事实表关联,一张事实表与多张维度表关联,事实表之间不进行相互关联。

该结构保证了无论用多少张维度表的维度去筛选多少张事实表的数据,都能马上得到正确结果。

而如果事实表之间直接建立关系,很容易出现用下级事实表的维度筛选上级事实表数据,这样所得到的计算结果往往是错误的,而且也影响性能。

website/blog/editor/media-46z0fnyw.png

2. 对雪花结构的处理

雪花结构是有多层级的维度表,如下图,产品大类表关联产品子类表,产品子类表关联产品表,再和事实表建立关系,这需要遍历较长的关系筛选器传播链,与应用于单个表的筛选器相比,效率更低。

对于这种结构,一般会在ETL或PQ中,将多张维度表联结成单张维度表,即将产品大类和子类放到产品表里,再由产品维度表与事实表关联。

website/blog/editor/media-fbynb2rr.png

3.对未建立关系结构的处理

在一些业务场景中,还会出现维度表与事实表不建立关系的情况,而是直接用DAX写度量值来判断当前所属维度,再给到对应的值。之所以没有建立关系,往往是因为维度表与事实表之间没有可关联的Key导致。

这种结构在一些辅助维度表中经常使用到,如:用于动态切片显示图表坐标轴,图表数据指标;这类应用场景因要判断的维度类别少,计算场景也较为简单,所以对性能不会产生太大影响。

但对于一些计算场景较为复杂,而且维度表内所需要判断的维度类别较多时,这种结构就会对性能产生很大的影响。

如下:三张用于呈现的维度表,未与任何事实表建立关系。

website/blog/editor/media-7ax4pprs.png

对于这种结构,处理方式就是给维度表和事实表都构造出一个Key列,使其能建立正确的关系,若无法构造出能直接建立关系的Key列,可以先构建出一张中间维度表,中间维度表一端与事实表相连,另一端与维度表相连。如下图:

website/blog/editor/media-numji7oe.png

如上模型,业务场景为:

维度表为各种费用类别,而各个费用类别的金额来源于事实表1的特定财务科目,特定成本中心,特定客户,特定账套组合,同时也来源于事实表2的不同数据列组合。如:类别1的金额为事实表1中科目为0001,0002,成本中心为X001,客户为A002,账套为C的金额,再加上事实表2的第X列金额。

各个费用类别之间存在包含关系,即类别3等于类别1和类别2之和,类别5等于类别3和类别4之和。即:需要显示在一个维度上的数据,实际上存在多层嵌套关系。

有些费用类别存在部分相同的取数逻辑。所以,针对会重复的类别,是无法构建key的,势必存在重复的key值。

针对以上业务场景,解决方案如下:

1. 构建事实表1的key值列

用SQL给事实表1构建key值列,该key列用于与中间维度表关联

website/blog/editor/media-4umlhauc.png

2. 将事实表2的二维表,逆透视成一维表,再构建key列

website/blog/editor/media-eimtxaee.png

3. 构建中间维度表

根据各个事实表的Key值所对应的类,构建中间维度表,与事实表关联的key在这个维度表中是唯一值,再给其对应上每个层级的类别;

另外,给中间维度表构建一个与最上层维度表关联的Key,这个Key根据各个层级的类别组合得到,是一个有重复值的列,用于与最上层的维度表关联。

website/blog/editor/media-3y09n89.png

4. 为最上层维度表添加key列

最上层维度表的Key列,根据要显示的费用类别给到对应的组合类别的Key,用于与中间维度表关联,建立关系。

website/blog/editor/media-6hypgg7f.png

5. 优化度量值

至此,已为没有关系的模型建立了关系,对于可以直接聚合的类,直接用聚合得到数值,对于一些不能直接聚合的类(如业务场景中出现会存在重复值的类,这种类无法为其创建唯一key),采用条件判断给到对一个数据。

website/blog/editor/media-m7hoep2.png

四、优化DAX

DAX的多层级嵌套判断使用,可以重复使用度量值,使得度量值的管理更高效,如报表A和报表B都用了同一个度量值,但是显示的数据是不同的,原因是两个报表有不同的筛选条件,而度量值内正是使用了对应的筛选条件判断,给出不同的值。

website/blog/editor/media-6r6hk2r.png

但这种嵌套的弊端是,拖慢了计算速度,对于相对简单的BI模型,这种多一层条件判断,一般不会有太明显的感觉,但对于BI模型计算较为复杂,而且引用的度量值已经多次嵌套时,再嵌套条件判断,会使得速度成倍缩减。

这时,应该拆分度量值,为A表建立A表使用的度量值,为B表建立B表使用的度量值,虽然度量值的数量增多了,但能很好的提升计算性能。

website/blog/editor/media-ag10xvs8.png

经过,以上各项优化,报表性能从优化前的114秒提升到3.4秒,整体报表性能都提升10倍以上。

website/blog/editor/media-9ojexh4h.png