(一) VAR案例
继续第一部分 (依据官方资料简体笔记)
使用变量优化 IF 条件
一个非常常见的使用变量来优化 DAX 中条件表达式 的优化模式。
在前面的文章中,已经显示了使用变量在 DAX 表达式中替换同一度量值的多个实例。其中还有一个非常常见的用例是 IF 函数模式。本节重点关注的是公式引擎而不是存储引擎的成本花费。
请考虑以下度量:
Margin := IF ( [Sales Amount] > 0
&& [Total Cost] > 0,[Sales Amount] - [Total Cost] )
其基本思路是:如果两个度量指标都大于零(满足两个IF条件),则执行[Sales Amount] - [Total Cost]求差值计算。本例中,DAX引擎会生成一个查询计划,对每个度量值进行两次评估。这在为以下类似查询生成的存储引擎请求中可见。
EVALUATE
SUMMARIZECOLUMNS ( 'Date'[Year],
"Margin", [Margin] )
但是,值得考虑的是,物理查询计划有216行,这是在跟踪相同度量值变化时要考虑的一个参考。
如果不涉及前一篇文章已经解释的细节,值得进一步提示的是,对同一度量值的多次引用都需要进行单独的计算,即便是结果相同。在相同的当前筛选中,DAX 不太擅长保存在同一筛选器环境中计算的公共子集(子表达式)的值。这一点在Margin(边际)计算的以下变化中显而易见。IF函数的两个分支相同,但查询计划为存储引擎和公式引擎添加了其他计算:
Margin 2 := IF ( [Sales Amount] > 0 && [Total Cost] > 0,
[Sales Amount] - [Total Cost], [Sales Amount] - [Total Cost])
本例中,存在一个额外的存储引擎查询,物理查询计划中的行数现在为 342,这在以前的工作负载中添加了超过50% 的行。
此度量值的优化版本,是考虑将两个度量分别存储为两个变量,以便在 IF 函数中将两个变量引用在一起,从而减少公式引擎请求计算的次数(仅计算一次)。
Margin Optimized :=
VAR SalesAmount = [Sales Amount]
VAR TotalCost = [Total Cost]
RETURN
IF ( SalesAmount > 0 && TotalCost > 0, SalesAmount – TotalCost)
这在存储引擎请求中是可见的:
如果与第一个分支相同的 IF 函数的版本比较,该版本将生成相同的存储引擎查询。但物理查询计划将行数从216减少到126。
这是一个重要的结果。因为 DAX 缓存只在存储引擎级别中运行,因此,当在公式引擎中请求对多个具有高成本的度量值的引用时,此优化技术尤其有用。
结论
在当前同一筛选器对同一度量值的多个引用,可以生成相同的 DAX 表达式的多次执行,从而产生相同的结果。在变量中保存度量结果会生成更好的查询计划,从而提高了 DAX 代码的性能。但同时还是前文所建议的注意:避免度量与原列表“存储”的重复,并根据数据模型大小等来判断你关注的是公式引擎还是存储引擎的成本花费。
未完待续