2016-11-03 6 views
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 ║ Measure1 ║ Measure2 ║

║ 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 Member ║ L2-4 ║ L1-99 ║ 4 ║ 8 ║

Результат правильный, но запрос очень медленный (> 4сек). Мой фактический запрос больше и содержит множество таких наборов и мер, поэтому кажется, что проблема заключается в существующей функции и общей структуре, которая предотвращает выполнение внутренних оптимизаций.

Такое решение является неправильным и уродливым, но как я могу его переписать и получить тот же результат быстрее?

+0

Вы можете заменить эти заявления '[уровень]. [Уровень] .CurrentMember .Member_Key = 'FirstSet'' для определенных членов, использующих оператор 'IS', например [Уровень]. [Уровень] .CurrentMember IS [Уровень]. [Уровень]. [Уровень]. [FirstSet] ' – whytheq

+0

Какова цель этих NULL-заявлений? 'MEMBER [Level]. [Level1]. [FirstSet] AS NULL' – whytheq

+0

Я попытался заменить оператор IS, но он не работает. Цель NULL-членов - просто создать пустую строку с определенным набором в ней для каждого члена в [Common CrossJoin Set] (или [Level]. [Level2] .Members). – VasiliyKapitanskiy

ответ

0

Я подозреваю, что узкое место, потому что, когда вы используете Iif ни один из логических ветвей NULL так что вы не получаете расчет режима блока: это лучший способ использования Iif: Iif(someBoolean, X, Null) или Iif(someBoolean, Null, x), но, к сожалению, в вашем случае не может иметь значение null.

Может быть, вы могли бы попробовать реализовать этот тип шаблона, предложенный Моша для замены 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] 
    ) 
) 

Теперь пытаются применить шаблон Моша (а не что-то я пробовал раньше, так что вам нужно будет настроить соответствующим образом)

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] 
+0

Hi whytheq, Благодарим вас за ответ. Я понял идею этого решения и внедрил его в свой запрос, чтобы результаты были одинаковыми, но пока нет улучшений в производительности. Даже подсчитанное количество клеток в MdxStudio почти одинаково. – VasiliyKapitanskiy

 Смежные вопросы

  • Нет связанных вопросов^_^