强制 DAX SWITCH 函数使用严格(惰性)短路评估

Ale*_*son 6 ssas lazy-evaluation switch-statement dax powerbi

设置: 类似于MSDN 论坛上的这个问题,我有一个可以在各种其他度量之间切换的度量(其中一些度量比其他度量复杂得多)。该措施看起来像这样(我的实际措施有更多情况):

VariableMeasure =
VAR ReturnType =
    SELECTEDVALUE ( ParamReturnType[ReturnType] )
SWITCH (
    ReturnType,
    "NAV", [Nav],
    "Income", [Income],
    "ROI", [Roi],
    "BM", [Benchmark],
    BLANK ()
)
Run Code Online (Sandbox Code Playgroud)

上下文: 切换度量的原因是能够通过选择ReturnType带有切片器的来选择要在报表上显示的度量,然后所选度量在矩阵视觉中显示为列标题。例如,我的矩阵可能如下所示:

矩阵视觉

(如您所见,它没有显示,BM因为它没有被选中。)


问题:问题是,当我刚刚NAV选择该度量时,尽管它是一种廉价的计算度量,但它仍然几乎与所有选择的度量一样慢。当我使用 DAX Studio 分析查询时,应该是一个简单的查询需要大约 2.7 秒。事实上,如果我用除[Nav]切换度量之外的度量注释掉这些行,性能会显着提高,运行时间不到 100 毫秒(快 30 倍)。DAX Studio 显示公式引擎 (FE) 负责大约 2.7 秒的 99.5%,而存储引擎 (SE) 使用不到 20 毫秒。


研究: 我阅读了以下 SQL BI 文章,其中提到了惰性/严格评估和短路:

了解 DAX 中的急切与严格评估

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

我的措施类似于第二个链接中的最后一个例子,但不像在他们的情况下那样从“短路评估”中受益。

此 Power BI 社区问题与此类似,但未提供其他见解。

这篇 Power BI 用户组社区帖子引用了几篇更有趣的文章,但不幸的是,这些文章最终都没有让我找到解决方案。


问题:我怎样才能让每个度量SWITCH独立于其他情况进行评估,因为构建查询计划以同时容纳所有情况会导致性能不佳?

我愿意接受解决我的问题的建议或变通方法,即使它没有严格回答这个问题。


附加信息:我有一种预感,查询引擎可能确实在严格评估 switch 函数,但只有在构建可以支持所有情况的通用查询之后,并且由于不同的度量是使用不同的逻辑构建的,所以这是非常低效的(并且还有我的情况与我提到的 SQL BI 示例不同)。


更新:

微软在 2021 年 5 月的 Power BI 更新中至少在一定程度上解决了这个问题:

https://powerbi.microsoft.com/en-us/blog/power-bi-report-server-may-2021-feature-summary/#perf

nin*_*key 0

在那篇文章的底部,马可回答了与您类似的问题。这里有一些可以尝试的想法:

1] 转换switch为switch( true, ... )

来自Dax.Guide/Switch您可以将 true 作为第一个参数传递给正文中的条件,例如:

VariableMeasure =
    VAR ReturnType =
        SELECTEDVALUE ( ParamReturnType[ReturnType] )

    var FinalValue =
        SWITCH (
            true,
            ReturnType = "NAV", [Nav],
            ReturnType = "Income", [Income],
            ReturnType = "ROI", [Roi],
            ReturnType = "BM", [Benchmark],
            BLANK ()
        )
return FinalValue
Run Code Online (Sandbox Code Playgroud)

2][Nav]如果没有使用则跳过

或者分支你的代码跳过[Nav]引用:

VariableMeasure =
    VAR ReturnType =
        SELECTEDVALUE ( ParamReturnType[ReturnType] ) 
        // tip: SELECTEDVALUE lets you set a default to return instead of blanks

    var UsingNav = 
        ReturnType = "NAV"

    var UsingNavFastValue =
        SWITCH (
            true,
            "NAV", [Nav],
            // ...
            "BM", [Benchmark],
            BLANK ()
        )

    var WithoutNav =
        SWITCH (
            ReturnType,
            "Income", [Income],
            // ... 
            "BM", [Benchmark],
            BLANK ()
        )

return if(
    UsingNav, UsingNavFastValue, WithoutNav )
Run Code Online (Sandbox Code Playgroud)

参考: