暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

DAX优化-使用变量优化IF和SWITCH表达式

BISeven 2021-11-17
2022

本文翻译自SQLBI


在DAX中,变量除了可以增强DAX代码的可读性外,还可以优化DAX的性能。因为如何能够正确使用变量,能够减少多次计算同一个表达式。然而,在某些情况下,使用变量有可能适得其反,对性能产生负面影响。

 

首先,让我们介绍一下变量是如何改善代码的执行。例如,考虑下面的报表,计算销量的YTD,仅仅考虑在这两年中有销量的月份。

 

计算Sales YTDOY的代码如下:

Sales YTDOY :=
CALCULATE (
SUMX (
VALUES ( 'Date'[Calendar Year Month Number] ),
VAR CurrentSales = [Sales Amount]
VAR PreviousSales = [Sales LY]
RETURN
IF (
AND (
CurrentSales <> 0,
PreviousSales <> 0
),
CurrentSales - PreviousSales
)
),
DATESYTD ( 'Date'[Date] )
)

 

这个度量值在IF语句和减法运算中,在每个月仅仅计算一次计算Sales Amount 和 Sales LY 。这很好,另一种方法是更短的代码但是多次调用相同的度量值

Sales YTDOY slow :=
CALCULATE (
SUMX (
VALUES ( 'Date'[Calendar Year Month Number] ),
IF (
AND (
[Sales Amount] <> 0,
[Sales LY] <> 0
),
[Sales Amount] - [Sales LY]
)
),
DATESYTD ( 'Date'[Date] )
)

 

虽然DAX引擎在相同的筛选上下文中可能会重复利用同一度量值的计算结果,但是并总是如此。在这种情景下,变量是保证优化代码性能的好方法。

 

然而,变量是在他们各自的定义域内使用。如果一个变量是在条件语句之前定义的,那么不管条件如何,该变量都将被计算,此时,如果报表中有断开连接的筛选器,那么性能将会受到很大的影响。为了说明这个情况,考虑如下的报表,使用一个切片器控制矩阵表中的列是否展现的报表。该报表包含一个度量值:Sales,其上下文取决于切片器的选择。

 

可以使用变量定义度量值:

Sales vSlow =
VAR PeriodSelection =
SELECTEDVALUE ( 'Time Selection'[PeriodSelector] )
VAR SalesAmount = [Sales Amount]
VAR SalesLY = [Sales LY]
VAR SalesYOY = [Sales YOY]
VAR SalesYTD = [Sales YTD]
VAR SalesLYTD = [Sales LYTD]
VAR SalesYTDOY = [Sales YTDOY]
RETURN
SWITCH (
PeriodSelection,
"C", SalesAmount,
"LY", SalesLY,
"YOY", SalesYOY,
"YTD", SalesYTD,
"LYTD", SalesLYTD,
"YTDOY", SalesYTDOY,
BLANK ()
)

 

对于这个度量值,没有什么特别原因非要这样定义。因为每个变量只是使用一次。但是,可以在PeriodSelection的多个表达式中重用变量,从而减少数据模型中定义的度量。尽管如此,我们可能期望以下代码获得相同的性能:

 

Sales vFast =
VAR PeriodSelection =
SELECTEDVALUE ( 'Time Selection'[PeriodSelector] )
RETURN
SWITCH (
PeriodSelection,
"C", [Sales Amount],
"LY", [Sales LY],
"YOY", [Sales YOY],
"YTD", [Sales YTD],
"LYTD", [Sales LYTD],
"YTDOY", [Sales YTDOY],
BLANK ()
    )

最后,我们在计算同一个条件语句:我们希望这个度量只有在使用时才计算,但是对IF和SWITCH函数的优化是值得的, 称为short-circut计算。它通过对IF和Switch的分支应用筛选器实现的。在vSlow度量值中,变量是在IF和Switch之前的同一定义域内定义的。因此,无论切片中选择了什么样的值,这些变量都会被计算一次。

 

这种行为的结果可能会严重影响结构良好的DAX的性能。因此,在使用变量时,最好遵循以下原则:

 

1. 当同一个DAX表达式在同一个筛选器上下文中多次计算时,将其赋值给一个变量,并引用该变量而不是

DAX表达式。

2. 当DAX表达式在IF或SWITCH的分支中求值时,无论什么时候,将表达式赋值给条件分支中的变量——这将保持shor-circut优化。

3. 如果变量只在条件分支中使用,则不要在IF或SWITCH语句之外定义变量。

4. IF和SWITCH的第一个参数可以使用在IF和SWITCH之前定义的变量,而不会影响性能

 

 

https://www.sqlbi.com/articles/optimizing-if-and-switch-expressions-using-variables/

 

 

 

 


文章转载自BISeven,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论