Ssas 快速动态命名集计算

Ssas 快速动态命名集计算,ssas,mdx,olap,query-performance,mdxstudio,Ssas,Mdx,Olap,Query Performance,Mdxstudio,我有一个长而复杂的查询,包含大量计算和条件,但主要结构如下所示: 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

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

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]
结果表如下所示:

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.第二组成员║ L2-3║ L1-98║ 3.║ 7.║

║ L2成员║ L1.第二组成员║ L2-4║ L1-99║ 4.║ 8.║

结果是正确的,但查询速度非常慢(>4秒)。我的实际查询更大,并且包含很多这样的集合和度量,所以问题似乎出在现有的函数和总体结构中,从而阻止引擎执行内部优化


这种解决方案是错误和丑陋的,但我如何重写它并更快地获得相同的结果呢?

我怀疑瓶颈是因为当您使用
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
的博文:

看看你的一个计算结果——这一个:

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的模式(我以前没有尝试过,所以您需要进行相应的调整)


我怀疑瓶颈是因为当您使用
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
的博文:

看看你的一个计算结果——这一个:

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的模式(我以前没有尝试过,所以您需要进行相应的调整)


您是否可以使用
IS
运算符替换这些语句,例如
[Level].[Level].[Level].[Level].[CurrentMember.Member_Key='FirstSet'
用于特定成员,例如
[Level].[Level].[Level].[FirstSet].[code>这些空语句的目的是什么?
成员[Level].[Level1].[FirstSet]AS NULL
我尝试用IS运算符替换,但不起作用。NULL成员的目的只是为[Common CrossJoin set](或[Level].[Level2].成员)中的每个成员创建一个空行,其中包含特定的集合。为什么不起作用?
是检查成员之间平等性的标准方法,速度会更快:是的,我知道。可能是因为本例中的成员为空,这就是为什么我通过名称设置的成员密钥进行比较。无论如何,此算法的比较部分不是瓶颈。总执行时间大约需要60-100毫秒离子时间,但它只是百分之几。您认为,也许还有其他方法可以从根本上重写查询?您能否替换这些语句
[Level].[Level].[Level]。CurrentMember.Member\u Key='FirstSet'
用于使用
is
运算符的特定成员,例如
[Level].[Level]。CurrentMember是[Level].[Level].[Level]。[FirstSet]
这些NULL语句的用途是什么?
成员[Level].[Level 1].[FirstSet]为NULL
我尝试用is运算符替换,但无效。NULL成员的用途只是为[Common CrossJoin set](或[Level].[Level 2].成员)中的每个成员创建一个空行,其中包含特定的集合。为什么不起作用?是检查成员之间平等性的标准方法,速度会更快:是的,我知道。可能是因为本例中的成员为空,这就是为什么我通过名称设置的成员密钥进行比较。无论如何,此算法的比较部分不是瓶颈。总执行时间大约需要60-100毫秒离子时间,但它只是百分之几。你认为,也许还有其他方法可以从根本上重写查询?嗨,whytheq,谢谢你的回答。我理解这个解决方案的想法,并在我的查询中实现了它,所以结果是一样的,但到目前为止性能没有任何改善。甚至计算出的单元格数也是一样的在MdxStudio中几乎相同。您好,whytheq,谢谢您的回答。我理解了此解决方案的思想,并在查询中实现了它,因此结果相同,但到目前为止性能没有任何改进。甚至在MdxStudio中计算的单元格数也几乎相同。