【问题标题】:Fast dynamic named set calculation快速动态命名集计算
【发布时间】:2016-11-03 12:34:42
【问题描述】:

我有一个很长的复杂查询,其中包含很多计算和条件,但主要结构如下所示:

WITH
MEMBER [Id1] AS [Level].[Level1].CurrentMember.Member_Key
MEMBER [Id2] AS [Level].[Level2].CurrentMember.Member_Key
MEMBER [Level].[Level1].[FirstSet] AS NULL
MEMBER [Level].[Level1].[SecondSet] AS NULL
SET [Set 1] AS {some processed set members}
SET [Set 2] AS {some other processed set members}
SET [Common CrossJoin Set] AS [Level].[Level2].Members

MEMBER [Calculated Measure 1] AS
  IIF([Level].[Level].CurrentMember.Member_Key = 'FirstSet',
    SUM(existing [Set 1]),
    IIF([Level].[Level].CurrentMember.Member_Key = 'SecondSet',
      SUM(existing [Set 2]),
      SUM([Measures].[Measure1]) * 15
    )
  )

MEMBER [Calculated Measure 2] AS
IIF([Level].[Level].CurrentMember.Member_Key = 'FirstSet',
  SUM(existing [Set 1]),
  IIF([Level].[Level].CurrentMember.Member_Key = 'SecondSet',
    SUM(existing [Set 2]),
    SUM([Measures].[Measure2]) * 20
  )
)
SELECT 
  { [Id1], [Id2], [Calculated Measure 1], [Calculated Measure 2]} ON COLUMNS,
  { ([Common CrossJoin Set], [Level].[Level1].[FirstSet]),
    ([Common CrossJoin Set], [Level].[Level1].[SecondSet])
  } ON ROWS
FROM [Cube]

所以结果表如下所示:

║ ---------------║ ---------------║ Id1 ║ Id2 ║ 测量 1 ║ 测量 2 ║

║L2成员║L1.FirstSet成员║L2-1║L1-8║1║5║

║L2成员║L1.FirstSet成员║L2-2║L1-9║2║6║

║L2成员║L1.SecondSet成员║L2-3║L1-98║3║7║

║L2成员║L1.SecondSet成员║L2-4║L1-99║4║8║

结果正确,但查询速度很慢(>4 秒)。我的实际查询更大,并且包含很多这样的集合和度量,所以看起来问题出在现有功能和整体结构中,阻止了引擎执行内部优化。

这种方案是错误的,丑陋的,但我怎样才能重写它并更快地得到相同的结果呢?

【问题讨论】:

  • 您能否使用IS 运算符替换这些语句[Level].[Level].CurrentMember.Member_Key = 'FirstSet' 用于确定的成员,例如[Level].[Level].CurrentMember IS [Level].[Level].[Level].[FirstSet]
  • 这些 NULL 语句的目的是什么? MEMBER [Level].[Level1].[FirstSet] AS NULL
  • 我尝试用 IS 运算符替换,但它不起作用。 NULL成员的目的只是为[Common CrossJoin Set](或[Level].[Level2].Members)中的每个成员创建一个包含特定集合的空行。
  • 为什么它不起作用 - IS 是检查成员之间相等性的标准方法,并且会更快:msdn.microsoft.com/en-us/library/ms145997.aspx
  • 是的,我知道。也许是因为在这种情况下 member 为 NULL,这就是为什么我通过 name 设置的 member_key 来比较它。无论如何,该算法的比较部分不是瓶颈。总执行时间大约需要 60-100 毫秒,但只有百分之几。您怎么看,也许还有其他方法可以从根本上重写查询?

标签: ssas mdx olap query-performance mdxstudio


【解决方案1】:

我怀疑瓶颈是因为当您使用Iif 时,两个逻辑分支都不是NULL,所以您没有得到块模式计算:这是使用Iif 的更好方法:Iif(someBoolean, X, Null)Iif(someBoolean, Null, x) 但不幸的是,在你的情况下,你也不能有 null。

也许您可以尝试实现 Mosha 建议的这种模式来替换 Iif

WITH 
MEMBER Measures.[Normalized Cost] AS [Measures].[Internet Standard Product Cost]
CELL CALCULATION ScopeEmulator 
  FOR '([Promotion].[Promotion Type].&[No Discount],measures.[Normalized Cost])' 
  AS [Measures].[Internet Freight Cost]+[Measures].[Internet Standard Product Cost]
MEMBER [Ship Date].[Date].RSum AS Sum([Ship Date].[Date].[Date].MEMBERS), SOLVE_ORDER=10
SELECT 
 [Promotion].[Promotion Type].[Promotion Type].MEMBERS on 0
 ,[Product].[Subcategory].[Subcategory].MEMBERS*[Customer].[State-Province].[State-Province].MEMBERS ON 1
FROM [Adventure Works]
WHERE ([Ship Date].[Date].RSum, Measures.[Normalized Cost])

这是来自这篇关于优化Iif的博客文章:http://sqlblog.com/blogs/mosha/archive/2007/01/28/performance-of-iif-function-in-mdx.aspx

所以看看你的一个计算 - 这个:

MEMBER [Calculated Measure 1] AS
  IIF([Level].[Level].CurrentMember.Member_Key = 'FirstSet',
    SUM(existing [Set 1]),
    IIF([Level].[Level].CurrentMember.Member_Key = 'SecondSet',
      SUM(existing [Set 2]),
      SUM([Measures].[Measure1]) * 15
    )
  )

我认为我们最初可以将其分解为:

MEMBER [Measures].[x] AS SUM(existing [Set 1])
MEMBER [Measures].[y] AS SUM(existing [Set 2])
MEMBER [Measures].[z] AS SUM([Measures].[Measure1]) * 15
MEMBER [Calculated Measure 1] AS
  IIF([Level].[Level].CurrentMember IS [Level].[Level].[Level].[FirstSet],
    [Measures].[x],
    IIF([Level].[Level].CurrentMember IS [Level].[Level].[Level].[SecondSet],
      [Measures].[y],
      [Measures].[z]
    )
  )  

现在尝试应用 Mosha 的模式(我之前没有尝试过,所以你需要相应地调整)

MEMBER [Measures].[z] AS SUM([Measures].[Measure1]) * 15
    MEMBER [Measures].[y] AS SUM(existing [Set 2])
    MEMBER [Measures].[x] AS SUM(existing [Set 1])
MEMBER [Calculated Measure 1 pre1] AS [Measures].[z]
CELL CALCULATION ScopeEmulator 
  FOR '([Level].[Level].[Level].[SecondSet],[Calculated Measure 1 pre1])' 
  AS [Measures].[y] 
MEMBER [Calculated Measure 1] AS [Calculated Measure 1 pre1]
CELL CALCULATION ScopeEmulator 
  FOR '([Level].[Level].[Level].[FirstSet],[Calculated Measure 1])' 
  AS [Measures].[x]

【讨论】:

  • 您好Whytheq,谢谢您的回答。我理解了这个解决方案的想法并在我的查询中实现了它,所以结果是一样的,但到目前为止性能没有任何改进。甚至在 MdxStudio 中计算的单元数也几乎相同。
猜你喜欢
  • 2020-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-21
  • 2010-12-23
  • 2011-11-27
  • 1970-01-01
相关资源
最近更新 更多