1

多くの計算と条件を含む長く複雑なクエリがありますが、主な構造は次のようになります。

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 ║</p>

║ L2 メンバー ║ L1.FirstSet メンバー ║ L2-1 ║ L1-8 ║ 1 ║ 5 ║</p>

║ L2 メンバー ║ L1.FirstSet メンバー ║ L2-2 ║ L1-9 ║ 2 ║ 6 ║</p>

║ L2 メンバー ║ L1.SecondSet メンバー ║ L2-3 ║ L1-98 ║ 3 ║ 7 ║</p>

║ L2 メンバー ║ L1.SecondSet メンバー ║ L2-4 ║ L1-99 ║ 4 ║ 8 ║</p>

結果は正しいが、クエリは非常に遅い (>4 秒)。私の実際のクエリはより大きく、そのようなセットとメジャーが多数含まれているため、エンジンが内部最適化を実行できないようにする既存の関数と全体的な構造に問題があるようです。

この種の解決策は間違っていて醜いですが、どうすれば書き直して同じ結果をより速く得ることができますか?

4

1 に答える 1

0

Iifどちらの論理ブランチも使用しない場合NULL、ブロックモードの計算が得られないため、ボトルネックが発生していると思われます。これはIif:を使用するより良い方法です。Iif(someBoolean, X, Null)Iif(someBoolean, Null, x)

たぶん、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

あなたの計算の1つを見ると、これは次のとおりです。

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]
于 2016-11-06T17:39:22.683 に答える