MDX - 过滤的 CROSSJOIN 计数 - 性能问题
Posted
技术标签:
【中文标题】MDX - 过滤的 CROSSJOIN 计数 - 性能问题【英文标题】:MDX - Count of Filtered CROSSJOIN - Performance Issues 【发布时间】:2014-03-17 11:19:56 【问题描述】:背景:我使用 MDX 已经有一段时间了,但我绝不是这方面的专家 - 寻求一些性能帮助。我正在 SQL Server Analysis Services 2012 多维数据集中处理一组“授权商店数/库存/销售/等”计算度量 (MDX)。我最初让这些计算表现良好,但发现它们并没有按照我需要的方式聚合到我的产品层次结构中。本报告中主要使用的两个层次结构是业务 -> 项目和部门 -> 商店。
例如,在原始 MDX 计算中,Stores In-Stock 度量将在“项目”级别正确执行,但不会将适当的总和汇总到其上方的“业务”级别。在业务层面,我们希望看到库存中商店/产品组合的总数,而不是最初看起来的不同或 MAX 值。
原始查询结果:这是一个不正常工作的示例(假设这是一个 Excel 数据透视表):
[FILTER: CURRENT WEEK DAYS]
[BUSINESS] [AUTH. STORES] [STORES IN-STOCK] [% OF STORES IN STOCK]
[+] Business One 2,416 2,392 99.01%
[-] Business Two 2,377 2,108 93.39%
-Item 1 2,242 2,094 99.43%
-Item 2 2,234 1,878 84.06%
-Item 3 2,377 2,108 88.68%
-Item N ... ... ...
固定查询结果:经过多次试验和错误,我转而使用 DESCENDANTS() 函数对两个层次结构的 CROSSJOIN() 进行过滤计数,从而产生正确的数字(如下):
[FILTER: CURRENT WEEK DAYS]
[BUSINESS] [AUTH. STORES] [STORES IN-STOCK] [% OF STORES IN STOCK]
[+] Business One 215,644 149,301 93.90%
[-] Business Two 86,898 55,532 83.02%
-Item 1 2,242 2,094 99.43%
-Item 2 2,234 1,878 99.31%
-Item 3 2,377 2,108 99.11%
-Item N ... ... ...
需要帮助的查询:这是产生上述结果的“新”查询:
CREATE MEMBER CURRENTCUBE.[Measures].[Num Stores In-Stock]
AS COUNT(
FILTER(
CROSSJOIN(
DESCENDANTS(
[Product].[Item].CURRENTMEMBER,
[Product].[Item].[UPC]
),
DESCENDANTS(
[Division].[Store].CURRENTMEMBER,
[Division].[Store].[Store ID]
)
),
[Measures].[Inventory Qty] > 0
)
),
FORMAT_STRING = "#,#",
NON_EMPTY_BEHAVIOR = [Inventory Qty] ,
此查询语法用于多维数据集中的一堆其他“正在销售/缺货/等的商店数量”类型的计算度量,只有底部的 [Inventory Qty] 条件或通过链接附加条件。
在目前的情况下,此查询可能需要 2-3 分钟才能运行,这对于此报告的受众来说太长了。谁能想到一种方法来减少查询负载或帮助我重写它以提高效率?
谢谢!
2014 年 2 月 24 日更新:我们通过绕过大量涉及的 MDX 并将标志值添加到 DSV 中的命名查询来解决了这个问题。
例如,我们没有在 MDX 代码中为“销售的商店数量”执行过滤命令 - 我们只是将其添加到名为查询的事实表中......
CASE WHEN [Sales Qty] > 0
THEN 1
ELSE NULL
END AS [Flag_Selling]
...然后我们简单地将这些度量聚合为多维数据集中的 LastNonEmpty。它们的汇总速度比完整的 MDX 查询快得多。
【问题讨论】:
【参考方案1】:将您的条件建模到立方体中应该更快,避免缓慢的Filter
函数:
如果只有少数几个条件,请为每个条件添加一个属性,其中包含两个值,一个表示条件满足,说“cond: yes”,一个表示条件不满足,说“cond: no”。您可以在物理事实表或 DSV 的视图中定义它,或者您可以对其进行物理建模。这些属性可以直接添加到事实表中,在同一个表上定义一个维度,或者更清楚地作为从事实表引用的单独维度表。然后将您的度量定义为
CREATE MEMBER CURRENTCUBE.[Measures].[Num Stores In-Stock]
AS COUNT(
CROSSJOIN(
DESCENDANTS(
[Product].[Item].CURRENTMEMBER,
[Product].[Item].[UPC]
),
DESCENDANTS(
[Division].[Store].CURRENTMEMBER,
[Division].[Store].[Store ID]
),
[Flag dim].[cond].[cond: yes]
)
)
您甚至可以将度量定义为事实表的标准计数度量。
如果有许多条件,则可能只添加一个属性,每个条件都有一个值作为多对多关系。这会稍微慢一些,但仍然比Filter
调用快。
【讨论】:
此数据也受时间限制,因此向维度添加属性不一定会起作用......但是我考虑过像您提到的那样在 DSV 中的事实表中添加二进制标志。我可能会尝试并报告。 我们继续按照您的建议将条件建模到立方体中,它的工作速度提高了大约 5 倍。猜猜我们是不是太喜欢 MDX 了!【参考方案2】:我相信您可以完全避免交叉连接和过滤。试试这个:
CREATE MEMBER CURRENTCUBE.[Measures].[Num Stores In-Stock]
AS
CASE WHEN [Product].[Item Name].CURRENTMEMBER IS [Product].[Item Name].[All]
THEN
SUM(EXISTS([Product].[Item Name].[Item Name].MEMBERS,[Business].[Business Name].CURRENTMEMBER),
COUNT(
EXISTS(
[Division].[Store].[Store].MEMBERS,
(
[Business].[Business Name].CURRENTMEMBER,
[Product].[Item Name].CURRENTMEMBER
),
"Measure Group Name"
)
))
ELSE
COUNT(
EXISTS(
[Division].[Store].[Store].MEMBERS,
(
[Business].[Business Name].CURRENTMEMBER,
[Product].[Item Name].CURRENTMEMBER
),
"Measure Group Name"
)
)
END
我尝试使用多维数据集中的维度并使用区域-附属层次结构。
案例语句处理在业务级别查看数据的情况。基本上,SUM()
在CASE
语句中使用的所有项目名称成员中计算各个项目名称的值,然后将所有值相加。我相信这就是您所需要的。
【讨论】:
以上是关于MDX - 过滤的 CROSSJOIN 计数 - 性能问题的主要内容,如果未能解决你的问题,请参考以下文章