Power BI Premium Tabular中MDX的NON_EMPTY_BEHAVIOR优化失效求助
微软一直在改进Power BI上的MDX查询语言,比如近期推出的“MDX Fusion”功能。虽然Power BI支持DAX查询,但MDX在数据分析中依然重要——它常用于Excel场景,还能在从OLAP源(SQL Analysis Services或Azure Analysis Services)以“导入”模式向Power Query导入数据时使用。
但实际使用中会遇到性能问题:自定义度量值无法通过NON_EMPTY_BEHAVIOR设置优化性能。示例查询如下:
WITH MEMBER [Measures].[NewSalesEmployeeId] as Iif(IsEmpty([Measures].[Units Sold]), NULL, "000000") , NON_EMPTY_BEHAVIOR=[Sales].[ValUnits] SELECT {{ [Measures].[Units Sold] , [Measures].[NewSalesEmployeeId] }} ON 0, NON EMPTY [Branch].[Branch Code].[Branch Code] * [Customer].[Customer Code].[Customer Code] * [Product].[Product Type Code].[Product Type Code] * [Product].[Descriptor - Species Code].[Descriptor - Species Code] * [Product].[Descriptor - Grade Code].[Descriptor - Grade Code] * [Product].[Descriptor - Grade Name].[Descriptor - Grade Name] * [Product].[Descriptor - Size Name].[Descriptor - Size Name] * [Product].[Descriptor - Thick Name].[Descriptor - Thick Name] * [Product].[Product Code].[Product Code] * [Product].[Length].[Length] * [Time].[Fiscal Day Value].[Fiscal Day Value] ON 1 FROM ( SELECT [Time].[Time F].[Week].[Y 2022 W 10] on 0 FROM (SELECT [Branch].[Branch Code].[Branch Code].[B123] on 0 from [Sales Budget and Activity]))
该查询耗时约3422毫秒,移除[Measures].[NewSalesEmployeeId]后仅需约80毫秒,最终结果仅约1000行,测试均在Power BI Premium P1模型的暖缓存环境下进行。
优化方案
修正
NON_EMPTY_BEHAVIOR的绑定目标
自定义度量值逻辑依赖[Measures].[Units Sold],但当前NON_EMPTY_BEHAVIOR指定的是维度属性[Sales].[ValUnits],这是不匹配的。NON_EMPTY_BEHAVIOR需要绑定到基础度量值,而非维度属性,这样引擎才能正确识别空值行并提前过滤。修改后的度量值定义如下:MEMBER [Measures].[NewSalesEmployeeId] as Iif(IsEmpty([Measures].[Units Sold]), NULL, "000000") , NON_EMPTY_BEHAVIOR=[Measures].[Units Sold]简化空值判断逻辑
用CoalesceEmpty函数替代Iif(IsEmpty(...)),该函数是MDX专门处理空值场景的原生函数,引擎对其优化支持更好:MEMBER [Measures].[NewSalesEmployeeId] as CoalesceEmpty([Measures].[Units Sold], "000000") , NON_EMPTY_BEHAVIOR=[Measures].[Units Sold]也可以用
IsNull函数简化语法,效果类似:MEMBER [Measures].[NewSalesEmployeeId] as IsNull([Measures].[Units Sold], "000000") , NON_EMPTY_BEHAVIOR=[Measures].[Units Sold]提前过滤空值行
如果NON_EMPTY_BEHAVIOR仍不生效,可以在行轴的NON EMPTY逻辑中,直接通过基础度量值过滤空行,再计算自定义度量值:NON EMPTY Filter( [Branch].[Branch Code].[Branch Code] * [Customer].[Customer Code].[Customer Code] * [Product].[Product Type Code].[Product Type Code] * [Product].[Descriptor - Species Code].[Descriptor - Species Code] * [Product].[Descriptor - Grade Code].[Descriptor - Grade Code] * [Product].[Descriptor - Grade Name].[Descriptor - Grade Name] * [Product].[Descriptor - Size Name].[Descriptor - Size Name] * [Product].[Descriptor - Thick Name].[Descriptor - Thick Name] * [Product].[Product Code].[Product Code] * [Product].[Length].[Length] * [Time].[Fiscal Day Value].[Fiscal Day Value], Not IsEmpty([Measures].[Units Sold]) ) ON 1这样先过滤掉无销售数据的行,减少后续自定义度量值的计算量。
将自定义度量值移至模型层
避免在MDX查询中临时定义度量值,直接在Power BI(或SSAS/AAS)模型中创建计算度量值,并在模型里设置好NON_EMPTY_BEHAVIOR属性。模型层的度量值会被引擎提前优化,性能远优于查询中临时定义的版本。
内容的提问来源于stack exchange,提问作者David Beavon

