跳至正文

【高级】Tableau性能优化之关键:两种计算对性能的影响实证

标签:

一直在犹豫要不要2022年写一本关于“数据准备”的书,详细的介绍数据准备、数据合并、数据模型的相关知识,后来觉得这个问题太technical,超过了自己的能力;所以把明年的这个计划改为了“Tableau高级案例集”。

不过,最近的几次客户活动,我分享了一些数据性能的部分,我突然发现一个问题,是之前盲区中没有发现的——关于样本范围的两种方式。我每次只是说“行级别的计算”性能低于聚合计算,但是很难提供明确的证据。前几天重写《数据可视化分析》筛选器的部分,同时受Power Bi中MDX语法的启发,理解了这个问题。

1

我们先来对比两个简单的计算实现一个相同的问题:

在2016年,每个类别、每个子类别的销售额总和

按照之前的分析框架,这里样本范围是“订单日期等于2016年”(所有的样本都可以转化为逻辑上的判断);问题描述是“类别*子类别”;问题答案是度量“销售额总和”,聚合回答答案。

先不考虑Tableau,先从Excel和SQL的角度,有两种方法:

方法1: 样本范围优先,然后计算聚合

为了对比性能之间的差异,这里使用SQL从数据库中查询,语法如下:

这里使用where创建筛选条件。全局的筛选减少了后面聚合的数据量。为什么这里有两个sum?是为了和后面做对比时尽可能保持一致。

反复执行五次,分别耗时 0.035秒、030秒、030秒、032秒、032秒,平均值0.0318秒

方法2:计算优先,在计算中增加筛选条件

第二种方法,把筛选条件写到sum聚合之中——这也是很多人喜欢在Tableau中写的方法。

同样,反复执行五次,时间分别是0.051秒、53秒、51秒、52秒、50秒,平均0.0514秒。明显高于之前的0.0318秒,后者比前者耗时增加了61%,或者说前者比后者减少38%。

2、

通过这种方式,我们可以更好的理解在之前一篇文章中的数据计算的两个位置。(详见:【经验】从分析角度看数据准备要点 V1.5

行级别计算和聚合计算

我把计算分为“行级别计算”和“聚合计算”两种,或者“非聚合计算”和“聚合计算”两种。只是,所有的分析都必须包含聚合过程,大部分的“非聚合计算”最终还是要通往聚合,所以就有了各种“建立在行级别计算基础上的聚合计算”。

我之前经常提及的一个“结构化分析”的案例,如上图所示。最后的“利润<0“的判断,可以视为行级别判断,但是视图中最终左右两侧聚合,是建立在这个行级别判断基础上的。和上面不同的是,这里没有筛选过程,所以必须是聚合中嵌套行级别判断。

但是,只要有筛选过程,优先的的筛选一定是放在独立的筛选过程中,Tableau的筛选器窗格,就像Excel透视表的筛选器、就像sql中的where条件,它们可以全局的缩减聚合的数据量,从而提高性能。

而如果把计算写到聚合之中,本质上不是筛选,而只是把一些数据强制转化为0或者null而已。很多人在写计算时,这么写:

2019年的销售额: if year(订单日期)=2019 then [销售额] end

2020年的销售额: if year(订单日期)=2020 then [销售额] end

然后使用二者再做聚合计算多年同比。这种方式变相地把筛选放在计算中,其实只是把不需要的数据改为了null,间接地实现计算的过程。

相比直接使用表计算的方法,上述的方法性能非常慢,性能应该是几倍的差异。如图所示,使用这种方式,耗时平均差不多0.06秒(相比之前只有一个判断,时间增加了20%)。

相比之下,如果使用where先筛选两年的数据,然后再聚合并分类,那么时间比之前还少,逻辑如下,平均值需要0.04秒——虽然看上去逻辑似乎复杂了很多,使用了多次日期转化函数。

总之,

在Tableau的计算中,从性能角度看,表计算优先,其次是LOD计算(作为预先聚合性能高于行级别),最后才是行级别(特别是把筛选放在计算过程中的“伪筛选”过程)。

喜乐君 May 24, 2021

了解 喜乐君 的更多信息

立即订阅以继续阅读并访问完整档案。

Continue reading