Быстрый запрос MDX для одной строки на иерархию в общем измерении

Работа с многомерным кубом SSAS, который включает измерение UserGroups, состоящее из нескольких иерархий. Каждая иерархия классифицирует пользователей как принадлежащих к определенной группе или нет. Пользователи могут принадлежать более чем к одной группе.

Попытка создать таблицу с одной строкой для каждой иерархии в измерении. Лучший подход, который я придумал, заключается в следующем:

WITH

    MEMBER [Measures].[Group Name] AS
        CASE
            WHEN [UserGroups].[Group A].CurrentMember.MemberValue <> 'All' THEN "Group A"
            WHEN [UserGroups].[Group B].CurrentMember.MemberValue <> 'All' THEN "Group B"
            -- More user groups...
            WHEN [UserGroups].[Group T].CurrentMember.MemberValue <> 'All' THEN "Group T"
            ELSE "Error"
        END
SELECT

{[Members].[Group Name], [Measures].[User Count], [Measures].[Revenue]} ON 0,

Order(
    UNION(
         [UserGroups].[Group A].&[True] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]},


         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].&[True]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]},

        -- A bunch more blocks so that there is one for each row.

         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].&[True]}
    ),
)
ON 1

FROM [Finances];

Это удается создать ожидаемую таблицу:

                    Group Name  User Count  Revenue
All  All  ... True  Group T     90          1800
...  ...  ... ...   ...         ...         ...
All  True ... All   Group B     20          400
True All  ... All   Group A     10          100

Однако запрос выполняется очень медленно. Любая заданная строка может быть вычислена изолированно примерно за 30 секунд. При объединении строк с помощью оператора UNION каждая дополнительная строка приводит к экспоненциальному увеличению времени вычислений, а не к желаемому линейному увеличению времени вычислений.

  • Почему наблюдается такое увеличение времени?
  • Есть ли способ указать базовому движку вычислять каждую строку изолированно?
  • Есть ли просто лучший способ выполнить этот запрос?

person Roy    schedule 07.04.2017    source источник
comment
Удивительно, что каждая строка такая медленная. Является ли User Count обычной мерой SUM? Сколько строк составляют таблицы фактов? Если вы только что сделали простой запрос для количества пользователей по группе А, сколько времени потребуется, чтобы получить эту одну ячейку? Как насчет доходов? Любые другие расчеты в игре, кроме того, что в вопросе?   -  person GregGalloway    schedule 08.04.2017
comment
Есть ли у вас возможность изменить куб? Измерение UserGroup «многие ко многим» имеет смысл. Дайте мне знать, если это вариант.   -  person GregGalloway    schedule 08.04.2017


Ответы (1)


Я думаю, вы уже экспериментировали с перестановкой запроса — если вы уберете UNION(...) из SELECT и сделаете его именованным SET в предложении WITH, поможет ли это?

WITH
    SET [RowSet] AS
       UNION(
         [UserGroups].[Group A].&[True] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]},


         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].&[True]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]},

        -- A bunch more blocks so that there is one for each row.

         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].&[True]}
    )
    MEMBER [Measures].[Group Name] AS
        CASE
            WHEN [UserGroups].[Group A].CurrentMember.MemberValue <> 'All' THEN "Group A"
            WHEN [UserGroups].[Group B].CurrentMember.MemberValue <> 'All' THEN "Group B"
            -- More user groups...
            WHEN [UserGroups].[Group T].CurrentMember.MemberValue <> 'All' THEN "Group T"
            ELSE "Error"
        END
SELECT

  {[Members].[Group Name], [Measures].[User Count], [Measures].[Revenue]} ON 0,

  Order(
    [RowSet],
)
ON 1
FROM [Finances];

Каково назначение функции ЗАКАЗ? Я не вижу, что вы заказываете?

Снова просто выстрел в темноте, но я думаю, что иногда я замечал разницу в эффективности между использованием UNION и использованием оператора + - так что еще один вариант:

WITH
    SET [RowSet] AS
       {
         [UserGroups].[Group A].&[True] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]}
       }
      +
       {
         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].&[True]} *
        -- More user groups...
        {[UserGroups].[Group T].[All]}
       }

        -- A bunch more blocks so that there is one for each row.
      +
       {
         [UserGroups].[Group A].[All] *
        {[UserGroups].[Group B].[All]} *
        -- More user groups...
        {[UserGroups].[Group T].&[True]}
       }
    MEMBER [Measures].[Group Name] AS
      ...
      ...

Извините, у меня нет определений - это просто варианты, которым может повезти!! Лучше всего как можно подробнее обсудить это с Грегом, так как он сможет дать вам дельный совет о возможных изменениях в дизайне куба.

person whytheq    schedule 08.04.2017