MDX - 过滤的CROSSJOIN计数 - 性能问题

时间:2014-02-17 23:24:07

标签: sql sql-server ssas mdx cross-join

背景:我一直在使用MDX,但我绝不是它的专家 - 寻找一些性能帮助。我正在研究SQL Server Analysis Services 2012多维数据集中的一组“授权/库存/销售/等等商店”计算度量(MDX)。我最初的这些计算表现很好,但发现它们并没有像我需要的那样聚合在我的产品层次中。本报告中主要使用的两个层次结构是Business - >项目和分部 - >存储。

例如,在原始MDX计算中,Stores In-Stock度量将在“Item”级别正确执行,但不会将适当的总和汇总到其上方的“Business”级别。在业务层面,我们希望看到库存中的商店/产品组合的总数,而不是原来看起来的不同或MAX值。

原始查询结果:以下是 NOT 正常工作的示例(想象一下这是一个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] }, 

此查询语法用于一堆其他“销售/缺货/等库存数量” - 在多维数据集中键入计算的度量,仅底部或通过[库存数量]条件的变化链接附加条件。

在目前情况下,此查询可能需要2-3分钟才能运行,这对于此报告的受众来说太长了。任何人都可以想到一种方法来减少查询负载或帮助我重写它以提高效率吗?

谢谢!


更新2014年2月24日:我们通过绕过大量涉及的MDX并在DSV中为我们的命名查询添加标记值来解决此问题。

例如,我们不是在MDX代码中为“商店销售数量”执行过滤命令,而是将其添加到名为query的事实表中......

CASE WHEN [Sales Qty] > 0 
    THEN 1 
    ELSE NULL 
END AS [Flag_Selling]

...然后我们简单地将这些度量聚合为多维数据集中的LastNonEmpty。它们比完整的MDX查询快得多。

2 个答案:

答案 0 :(得分: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调用快。

答案 1 :(得分:1)

我相信你可以避免交叉连接以及完全过滤。试试这个:

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

我在我的多维数据集中使用维度并使用Area-Subsidiary层次结构尝试了它。 case语句处理在业务级别查看数据的情况。基本上,SUM()语句中使用的所有项目名称成员的CASE计算单个项目名称的值,然后汇总所有值。我相信这就是你所需要的。