|
|
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Коллеги, сам я от SSAS отошел давно (может кто-то меня "динозавра" еще помнит здесь), но в соседней команде возникла проблема, поэтому решил обратиться сюда к давним знакомым :) Ситуация следующая. В соседнем проекте используется табулярный Analysis Services как PaaS в ажуре. Раньше был куб в обычном multidimensional, но "политика партии" продиктовала "перейти на PaaS", а там только табулярка. ОК, они переделали куб на табулярку. Жрет на старте 30 гиг оперативки (данных 6 миллиардов строк). Но ексельных отчетов было дофига и чуть чуть, и эти ексельные отчеты пуляют MDX (а не DAX) на эту табулярку. И вот как только пользователи активизируются с запросами - это все начинает жрать 200 гиг оперативки. Майкрософт конечно счастлив, потому что косит бабло в своем Ажуре. А заказчик негодует по этому поводу. Жалуется что "а это вы плохо сделали табулярный куб". Я в этом проекте не учавствую совсем - здесь спрашиваю потому, что просто решил помочь коллегам. И я логично понимаю, что надо было бы либо поднять multidimensional SSAS в IaaS-е (отдельная виртуалка), его нормально оттюнать (секционирование, агрегации, оптимизировать калки и т.д.) и тогда пускай юзают свои ексель-отчеты, либо же второй вариант - сразу заказчику говорить "хочешь переходить на табулярку? ок, но тогда при условии что мы и все отчеты твои переводим на клиента, понимающего DAX, например PowerBI". Но уже поздно: заказчик закомандовал табулярку в PaaS, а отказываться от отчетов на Екселе не собирается. Вопрос звучит так: что бы вы посоветовали сейчас делать? Т.е. как понять, почему MDX->DAX конвертер генерирует тупые DAX-запросы, какие именно DAX-запросы тупят, и можно ли вообще помочь как-то в этом случае? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.08.2019, 13:47 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Заказчик захотел. Заказчик получил. Чего париться ? Это его проблемы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.08.2019, 15:26 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
1. Уменьшите параметр агрессивного освобождения памяти, по умолчанию он равен 80%; 2. Обратите внимание на меры, которые используют функции SumX, RankX и т.д. - эти функции охотно жрут памать, минимизируйте выборку для обхода. Так же пересмотрите листинг мер, которые содержат группировку SummaRize, GroupBy с целью использования контекста фильтрации; 3. Заказчик скорее всего прав, структуру куба внимательно просмотрите еще раз. 6 миллиардов строк это не так уж и много для табулярки. "эти ексельные отчеты пуляют MDX (а не DAX) на эту табулярку" - это нормально, Ексель не знает Dax, но сервер его отлично понимает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.08.2019, 15:56 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
IDVT Дополню коллегу Но уже поздно: заказчик закомандовал табулярку в PaaS, а отказываться от отчетов на Екселе не собирается. Ексель не знает Dax, но сервер его отлично понимает. >> Хоть и понимает, но результаты (время) выполнения MDX в 1.5-1.8 раза ниже, чем DAX. Сам Excel и Azure SSAS по опыту работы - недостойная связка. Просто Excel - не идеальный инструмент и использовать его вне ЛВС компании при доступе к внешниму Azure SSAS, -всегда будет медленно. Скажи проверить еще раз структуру модели на используемые типы и выполнить их максимальную минимизацию или разбиение (сократить размеры модели). Обратить внимание на Encoding и Compression (Vertipaq Analyzer) Использовать Azure SSAS реплики при обновлении модели п.с. 30Gb RAM для 6 млрд похоже и ожидаемо. Меньше 100Гб RAM для среднего in-memory проекта (S4 Standard, ~6K $/month) особого смысла использовать не вижу. Как вариант, попробовать Azure DWH +DirectQuery. Так же наблюдал нередко случаи при построении таблицы в Excel при пересечении на строках 2-х достаточно больших атрибутов измерений (по колву элементов 3-5 сотен тысяч), тот же всеми распиаренный distinct count по значению в ТФ мог уходить в ожидание 10-15 минут на результирующий датасет в 5-7 тыс строк, при этом QPU уходило в потолок и там и оставалось :) Имею устойчивое понимание, что Azure SSAS (PaaS) менее управляем, чем IaaS (On-prem in VM) Игорь Бобак, ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.08.2019, 17:58 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
L_argoЗаказчик захотел. Заказчик получил. Чего париться ? Это его проблемы. ++ Золотые слова! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2019, 00:10 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Игорь БобакВопрос звучит так: что бы вы посоветовали сейчас делать? Выставить ценник ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2019, 00:11 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
sergeynsИгорь БобакВопрос звучит так: что бы вы посоветовали сейчас делать? Выставить ценник С этим у заказчика проблем нет: выставим - оплатит. Вопрос был в том, что делать чтобы вырулить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2019, 10:36 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Voyager_lan, "Как вариант, попробовать Azure DWH +DirectQuery." -далеко не все DAX фукции поддерживаются в DirectQuery мод. Плюс скорость вычислений в данном случае небудет быстрее чем InMemory, мне кажется. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2019, 11:22 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Voyager_lanIDVT Скажи проверить еще раз структуру модели на используемые типы и выполнить их максимальную минимизацию или разбиение (сократить размеры модели). Обратить внимание на Encoding и Compression (Vertipaq Analyzer) Использовать Azure SSAS реплики при обновлении модели Добрый день, а можно немного подробнее вот по этому пункту? Просто я являюсь как раз членом той "соседней команды" у которой и есть все эти проблемы. Что именно тут необходимо сделать? 1. Проверить структуру модели на используемые типы? - Что именно тут нужно проверить? Дело в том, что сама модель очень медленно работает да же в Visual Studio и порой любые изменения в калькуляциях/мерах приходится ждять по нескольку минут, пока отвиснит студия. В модели порядка 40 фактовых таблиц и 10 дименшенов. Соответсвенно практически все фактовые таблицы имеют порядка 10 связей к дименшенам. Фактовые таблицы очень большие. (большинство из них имеют сотни млн. строк) Мне кажется уже это дает какие-то тормоза. Типы данных в основном String. Изначально и связи идут по String полям. Например поле ProductID сейчас имеет значение вида: "c4ab4bae-95f6-4938-b25a-f0fc97bd8e52" и так по всем ID. Изначально это были нормаьные ID вида 78541, но потом палитика партии поменялась и сейчас это UID (автоматически сгененрирвоанные уникальные ID). По этой причинесвязи идут по текстовым полям. 2. выполнить их максимальную минимизацию или разбиение - Я так понимаю речь идет о самих мерах/калькуляциях в модели? Вот тут есть так же "тонкий" момент. Дело в том, что как уже сказал Игорь, заказчик очень упертый и не хочет идти на компромисы. В табулярной модели нет возможности использовать "CREATE MEMBER" функцию, а в их старом солюшене (мудбтидименщене) они использовали это повсюду. Так например, у них были сделаны среды по некоторым заранее предусмотренным периодам времени в однм из дименшенов. Т.е они в Дименшене "Period" сделали один дефолтный, а остальные генерили внутри куба (порядка 10 значений типа MTD, QTD, YTD, Last Year и так далее). Нам пришлось делать workaround - отдельно делать меры для подсчета каждой меры под разные срезы, делать их невидимыми для пользователей, а потом делать одну общую меру, в которой проверками , в зависимост и от того, что было выбрано пользователем в фильтрах, запускать нужную меру. (надеюсь понятно расписал, а то как-то скомкано получилось). 3. Обратить внимание на Encoding и Compression (Vertipaq Analyzer) - а что конкретно тут надо посмотреть. В данный момент у нас вообще опция "Memory\VertiPaqPagingPolicy" выключена. Вот текущие настройки нашего сервера касательно памяти. У нас Pricing tier = S8 с 200 Gb memory и нам этого явно не хватает сейчас порой. HardMemoryLimit - 45 LowMemoryLimit - 65 TotalMemoryLimit - 35 VertiPaqMemoryLimit - 35 Не знаю кто их выставлял и на чем основывался, но могу предположить, что это были дефолтные днастройки. Может быть кто-то порекомендует как их точнее выставить? 4. Использовать Azure SSAS реплики при обновлении модели - Правильно ли я понимаю, что речь идет об настройках из Azure Portal вида "Number of query replicas" и "Separate the processing server from querying pool"? Я так понимаю после включения этих опция цена сервера повышается в два раза ... т.е это равнозначно тому, что появляется второй сервер на заднем фоне и за него бирется такая же цена как за основной. Мы как-то включали такое, но разницы не особо заметили, возможно не до конца разобрались с настройками. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2019, 12:54 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
1. "порядка 10 значений типа MTD, QTD, YTD, Last Year и так далее). Нам пришлось делать workaround" -> PARALLELPERIOD? 2. "В модели порядка 40 фактовых таблиц" и их нельзя объединить в меньшее количество таблиц (Union), с целью уменьшения количества словарей? 3. В модели есть расчетные атрибуты или измерения? 4. "а потом делать одну общую меру" - покажите листинг одной из таких мер, и несколько мер которыми она оперирует. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2019, 13:21 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
IDVT, 1. Не совсем, дело в том, что в модели мы используем сразу два календаря, Грегорианский и Финансовый (недельный), и как оказалось PARALLELPERIOD не верно работает с Finance Calendar (недельный календарь), по этой причине мы расчитываем start day и last day для периода в зависимости от того, что выбрано в фильтре (год, квартал, месяц, неделя, день) и делаем CALCULATE с фильтрацией по этому периоду. 2. Нет, на текущий момент это не возможно, дело в том , что все эти таблицы сгрупированы по своему определеному полю (Товару, Компании, категории и атк далее) и это сделано для каждого из двух календарей (Грегорианского и Финансового) и далее на каждой из этих таблиц делается вычисление вида DISTINCT COUNT. И затем уже, в зависимости от того какой уровень групировки используется в очтете данные вытягиваются из нужной таблички. 3. У нас есть только несколько калькулируемых колонок в табличках (буквально две или три и все) В Tabular model не существует CREATE MEMBER или CREATE CELL калькуляций 4. Листинг мер: Как я уже сказал выше, заказчик в своих отчетах использует 2 календаря. Потому мы делаем калькуляции все в двух видах (для обоих календарей). Кроме того, в прошлой модели у заказчика было несколько CREATE MEMBER созданных внутри куба, а не на стороне DWH. A. Period Dimension: "Current", - в DWH только этот "Last Year", "Diff", "vs LY %", "MTD", "MTD LY", "MTD Diff", "MTD vs LY %", "QTD", "QTD LY", "QTD Diff", "QTD vs LY %", "YTD", "YTD LY", "YTD Diff", "YTD vs LY %" B. Class Dimension Male, Female, Male+Female - Калькулируемый в кубе Ну вот лень им каждый раз тыкать MALE и FEMALE в списках, хотят сразу галочку MALE+FEMALE и это для них принципиально, потому что так было раньше и они не хотят по другому сейчас. Получается, что мы сделали этих MEMBERS не на стороне куба, а на стороне DWH мемберами в Dimensions и в DAX мерах в самом кубе вынуждены просчитывать сразу все варианты для всех срезов , но выводить данные только те, что выбраны в фильтрах заказчика. Т.е мы в мере считаем и "Current" и "Last Year" и "Male" и "Female" и "MALE+FEMALE" , но если в репорте в фильтре был выбран вариант Period Dimension только "Current" и только "MALE+FEMALE", то выводим только эти значения. Есть подозрение, что все меры в любом случае высчитываются и только потом фильтруется, но как я сказал мы постарались их разделить на разные метрики, чтобы это предотвратить. Изначально была одна большая мера со всеми Пириодами для Грегорианского календаря и одна для Финансового календаря. Потом разделили их на несколько маленьких сгрупированных по Периодам (Год, квартал, месяц и так далее), которые вызываются одной главной мерой. Проблема с Периодами еще была и в том, что часть мемберов должны возвращаться в другом формате (в процентах), а часть в определнных шаблоназ (типа 4 знака после запятой или 2 знака после запятой). Формат выставляем в свойствах меры: "FORMAT STRING" - тогда само Value меры возвращается как число в Excel (это очень важно для заказчика). А если мы используем DAX функцию FORMAT - то значение возвразается как текст, потому что эта функция сама по себе конвертит все в текст. В итоге процентные значения у нас возвращаются как текст. Получается, что одна мера должна возвращать значения в двух разных форматах. В мультидименшен модели это делалось тем же свойством но для отдельного CREATE MEMBER можно было вставить свой FORMAT_STRING. дополнительнонадо проверять и еще один вариант, если в фильтре был вывран мембер "MALE+FEMALE" - т.е внутри куба мы внутри каждой метрики делаем подсчет вида: MALE+FEMALE = (взять value MALE) + (взять value FEMALE) и возвращаем если это было выбрано в фильтре. Пример мер ниже: SALARY_MAIN SALARY:= IF( ISCROSSFILTERED('Period Dimension') && ISCROSSFILTERED('Finance Calendar'), SWITCH (SELECTEDVALUE('Period Dimension'[Period Dimension_],"Current"), "Current", [SALARY_FC_LY], "Last Year", IF(HASONEVALUE('Finance Calendar'[YearNumber]), [SALARY_FC_LY], BLANK()), "Diff", IF(HASONEVALUE('Finance Calendar'[YearNumber]), [SALARY_FC_LY], BLANK()), "vs LY %", IF(HASONEVALUE('Finance Calendar'[YearNumber]), IF(ISBLANK([SALARY_FC_CR_vs_LY_%]), BLANK(),FORMAT([SALARY_FC_CR_vs_LY_%], "#,#0.0%;-#,#0.0%")), BLANK()), "MTD", IF(HASONEVALUE('Finance Calendar'[Period DimensionNumber]), [SALARY_FC_MTD],BLANK()), "MTD LY", IF(HASONEVALUE('Finance Calendar'[Period DimensionNumber]), [SALARY_FC_MTD] ,BLANK()), "MTD Diff", IF(HASONEVALUE('Finance Calendar'[Period DimensionNumber]), [SALARY_FC_MTD],BLANK()), "MTD vs LY %", IF(HASONEVALUE('Finance Calendar'[Period DimensionNumber]), IF(ISBLANK([SALARY_FC_MTD_vs_LY_%]), BLANK(),FORMAT([SALARY_FC_MTD_vs_LY_%], "#,#0.0%;-#,#0.0%")),BLANK()), "QTD", IF(HASONEVALUE('Finance Calendar'[QuarterNumber]), [SALARY_FC_QTD], BLANK()), "QTD LY", IF(HASONEVALUE('Finance Calendar'[QuarterNumber]), [SALARY_FC_QTD] ,BLANK()), "QTD Diff", IF(HASONEVALUE('Finance Calendar'[QuarterNumber]), [SALARY_FC_QTD], BLANK()), "QTD vs LY %", IF(HASONEVALUE('Finance Calendar'[QuarterNumber]), IF(ISBLANK([SALARY_FC_QTD_vs_LY_%]), BLANK(),FORMAT([SALARY_FC_QTD_vs_LY_%], "#,#0.0%;-#,#0.0%")),BLANK()), "YTD", IF(HASONEVALUE('Finance Calendar'[YearNumber]), [SALARY_FC_YTD], BLANK()), "YTD LY", IF(HASONEVALUE('Finance Calendar'[YearNumber]), [SALARY_FC_YTD], BLANK()), "YTD Diff", IF(HASONEVALUE('Finance Calendar'[YearNumber]), [SALARY_FC_YTD], BLANK()), "YTD vs LY %", IF(HASONEVALUE('Finance Calendar'[YearNumber]), IF(ISBLANK([SALARY_FC_YTD_vs_LY_%]), BLANK(),FORMAT([SALARY_FC_YTD_vs_LY_%], "#,#0.0%;-#,#0.0%")),BLANK()) ), IF(ISCROSSFILTERED('Period Dimension') && ISCROSSFILTERED('Gregorian Calendar'), SWITCH (SELECTEDVALUE('Period Dimension'[Period Dimension_],"Current"), "Current", [SALARY_GC_LY], "Last Year", IF(HASONEVALUE('Gregorian Calendar'[YearNumber]), ... "Diff", IF(HASONEVALUE('Gregorian Calendar'[YearNumber]), ... "vs LY %", IF(HASONEVALUE('Gregorian Calendar'[YearNumber]), ... "MTD", IF(HASONEVALUE('Gregorian Calendar'[Period DimensionNumber]), ... "MTD LY", IF(HASONEVALUE('Gregorian Calendar'[Period DimensionNumber]), ... "MTD Diff", IF(HASONEVALUE('Gregorian Calendar'[Period DimensionNumber]), ... "MTD vs LY %", IF(HASONEVALUE('Gregorian Calendar'[Period DimensionNumber]), ... "QTD", IF(HASONEVALUE('Gregorian Calendar'[QuarterNumber]), ... "QTD LY", IF(HASONEVALUE('Gregorian Calendar'[QuarterNumber]), ... "QTD Diff", IF(HASONEVALUE('Gregorian Calendar'[QuarterNumber]), ... "QTD vs LY %", IF(HASONEVALUE('Gregorian Calendar'[QuarterNumber]), ... "YTD", IF(HASONEVALUE('Gregorian Calendar'[YearNumber]), ... "YTD LY", IF(HASONEVALUE('Gregorian Calendar'[YearNumber]), ... "YTD Diff", IF(HASONEVALUE('Gregorian Calendar'[YearNumber]), ... "YTD vs LY %", IF(HASONEVALUE('Gregorian Calendar'[YearNumber]), ... ), [SALARY_CR] ) ) Если выбрано "Last Year" SALARY_FC_LY:= /* --Current Year selected values: */ VAR CY = YEAR(NOW()) VAR SY = SELECTEDVALUE('Finance Calendar'[YearDescription],YEAR(NOW())) VAR SQ = SELECTEDVALUE('Finance Calendar'[QuarterDescription]) VAR SM = SELECTEDVALUE('Finance Calendar'[PeriodDescription]) VAR SW = SELECTEDVALUE('Finance Calendar'[WeekDescription]) /* --Previous Year selected values: */ VAR PeriodLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[PeriodDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) VAR QuarterLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[QuarterDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) VAR YearLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[YearDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) VAR WeekLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[WeekDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) VAR DayLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[DayDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) /* Choose MAX Date depend on Time interval (Week/MonthQuarter/Year) */ VAR Max_Date_Interval = SWITCH(TRUE(), ISINSCOPE('Finance Calendar'[DayDescription]), CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[WeekDescription] = WeekLastYear && 'Finance Calendar'[DayNumber] = SELECTEDVALUE('Finance Calendar'[DayNumber]) ) ) , ISINSCOPE('Finance Calendar'[WeekDescription]),CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[WeekDescription] = WeekLastYear ) ) , ISINSCOPE('Finance Calendar'[PeriodDescription]), CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[PeriodDescription] = PeriodLastYear ) ) , ISINSCOPE('Finance Calendar'[QuarterDescription]),CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[QuarterDescription] = QuarterLastYear ) ) , ISINSCOPE('Finance Calendar'[YearDescription]), CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[YearDescription] = YearLastYear ) ) ) /* Max Date for Week*/ var Max_Date_Week = CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[WeekDescription] = WeekLastYear ) ) /*Max Date for LY calculation */ var Max_Date = CALCULATE ( MAX('Finance Calendar'[DayDescription]) ) VAR Max_DateLastYear = REPLACE(Max_Date,3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) /*Min Date for LY calculation */ var Min_Date = CALCULATE ( MIN('Finance Calendar'[DayDescription]) ) VAR Min_DateLastYear = REPLACE(Min_Date,3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) /* --Calculations: */ VAR SELECTED_PERIOD_CY = IF (SELECTEDVALUE('Class'[Class_Total], "Class_Total")= "MALE+FEMALE", CALCULATE([SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"}), CALCULATE([SALARY] - [TAX] ) ) VAR SELECTED_PERIOD_LY = IF (SELECTEDVALUE('Class'[Class_Total], "Class_Total")= "MALE+FEMALE", SWITCH(TRUE(), ISINSCOPE('Finance Calendar'[DayDescription]), CALCULATE ( [SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"}, FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[DayDescription] = DayLastYear ) ) , ISINSCOPE('Finance Calendar'[WeekDescription]), CALCULATE ( [SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"}, FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[WeekDescription] = WeekLastYear ) ) , ISINSCOPE('Finance Calendar'[PeriodDescription]), CALCULATE ( [SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"}, FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[PeriodDescription] = PeriodLastYear ) ) , ISINSCOPE('Finance Calendar'[QuarterDescription]), CALCULATE ( [SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"}, FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[QuarterDescription] = QuarterLastYear ) ) , ISINSCOPE('Finance Calendar'[YearDescription]), CALCULATE ( [SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"}, FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[YearDescription] = YearLastYear ) ) , 0 ) , SWITCH(TRUE(), ISINSCOPE('Finance Calendar'[DayDescription]), CALCULATE ( [SALARY] - [TAX], FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[DayDate] = Max_Date_Interval ) ) , ISINSCOPE('Finance Calendar'[WeekDescription]), CALCULATE ( [SALARY] - [TAX], FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[WeekDescription] = WeekLastYear ) ) , ISINSCOPE('Finance Calendar'[PeriodDescription]), CALCULATE ( [SALARY] - [TAX], FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[PeriodDescription] = PeriodLastYear ) ) , ISINSCOPE('Finance Calendar'[QuarterDescription]), CALCULATE ( [SALARY] - [TAX], FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[QuarterDescription] = QuarterLastYear ) ) , ISINSCOPE('Finance Calendar'[YearDescription]), CALCULATE ( [SALARY] - [TAX], FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[YearDescription] = YearLastYear ) ) , 0 ) ) RETURN IF(SELECTEDVALUE('Period Dimension'[Period Dimension_],"Current") = "Current", SELECTED_PERIOD_CY, IF(SELECTEDVALUE('Period Dimension'[Period Dimension_],"Current") = "Last Year", SELECTED_PERIOD_LY, IF(SELECTEDVALUE('Period Dimension'[Period Dimension_],"Current") = "Diff", IF(SELECTED_PERIOD_LY = 0, BLANK(),SELECTED_PERIOD_CY - SELECTED_PERIOD_LY) ) ) ) Если сли выбрано "MTD" SALARY_FC_MTD:= /* --Current Year selected values: */ VAR CY = YEAR(NOW()) VAR SY = SELECTEDVALUE('Finance Calendar'[YearDescription],YEAR(NOW())) VAR SQ = SELECTEDVALUE('Finance Calendar'[QuarterDescription]) VAR SM = SELECTEDVALUE('Finance Calendar'[PeriodDescription]) VAR SW = SELECTEDVALUE('Finance Calendar'[WeekDescription]) /* --Previous Year selected values: */ VAR PeriodLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[PeriodDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) VAR QuarterLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[QuarterDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) VAR YearLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[YearDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) VAR WeekLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[WeekDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) VAR DayLastYear = REPLACE(SELECTEDVALUE('Finance Calendar'[DayDescription]),3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) /* Choose MAX Date depend on Time interval (Week/MonthQuarter/Year) */ VAR Max_Date_Interval = SWITCH(TRUE(), ISFILTERED('Finance Calendar'[DayDescription]), CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[WeekDescription] = WeekLastYear && 'Finance Calendar'[DayNumber] = SELECTEDVALUE('Finance Calendar'[DayNumber]) ) ) , ISFILTERED('Finance Calendar'[WeekDescription]),CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[WeekDescription] = WeekLastYear ) ) , ISFILTERED('Finance Calendar'[PeriodDescription]), CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[PeriodDescription] = PeriodLastYear ) ) , ISFILTERED('Finance Calendar'[QuarterDescription]),CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[QuarterDescription] = QuarterLastYear ) ) , ISFILTERED('Finance Calendar'[YearDescription]), CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[YearDescription] = YearLastYear ) ) ) /* Max Date for Week*/ var Max_Date_Week = CALCULATE ( MAX('Finance Calendar'[DayDate]), FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[WeekDescription] = WeekLastYear ) ) /*Max Date for LY calculation */ var Max_Date = CALCULATE ( MAX('Finance Calendar'[DayDescription]) ) VAR Max_DateLastYear = REPLACE(Max_Date,3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) /*Min Date for LY calculation */ var Min_Date = CALCULATE ( MIN('Finance Calendar'[DayDescription]) ) VAR Min_DateLastYear = REPLACE(Min_Date,3,2, RIGHT(SELECTEDVALUE('Finance Calendar'[YearNumber]) - 1,2) ) /* --Calculations: */ VAR MTD_CY = IF (SELECTEDVALUE('Class'[Class_Total], "Class_Total")= "MALE+FEMALE", CALCULATE ( [SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"}, FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[PeriodDescription] = SM && 'Finance Calendar'[DayDescription] <= Max_Date ) ) , CALCULATE ( [SALARY] - [TAX], FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[PeriodDescription] = SM && 'Finance Calendar'[DayDescription] <= Max_Date ) ) ) VAR MTD_LY = IF (SELECTEDVALUE('Class'[Class_Total], "Class_Total")= "MALE+FEMALE", CALCULATE ( [SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"}, FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[PeriodDescription] = PeriodLastYear && 'Finance Calendar'[DayDate] <= Max_Date_Interval ) ) , CALCULATE ( [SALARY] - [TAX], FILTER ( ALL('Finance Calendar'), 'Finance Calendar'[PeriodDescription] = PeriodLastYear && 'Finance Calendar'[DayDate] <= Max_Date_Interval ) ) ) RETURN IF(SELECTEDVALUE('Period Dimension'[Period Dimension_],"Current") = "MTD", MTD_CY, IF(SELECTEDVALUE('Period Dimension'[Period Dimension_],"Current") = "MTD LY", MTD_LY, IF(SELECTEDVALUE('Period Dimension'[Period Dimension_],"Current") ="MTD Diff", IF(MTD_LY = 0, BLANK(), MTD_CY - MTD_LY) ) ) ) Если не выбран "Period Dimension" - этот вариант, кстати, работает очень быстро и практически не потребляет памяти SALARY_CR:= IF( ISBLANK(IF (SELECTEDVALUE('Class'[Class_Total], "Class_Total")= "MALE+FEMALE", CALCULATE( [SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"} ), CALCULATE( [SALARY] - [TAX] ) ) ), BLANK(), IF (SELECTEDVALUE('Class'[Class_Total], "Class_Total")= "MALE+FEMALE", CALCULATE( [SALARY] - [TAX], ALL('Class'),'Class'[Description] in {"Male","Female"} ), CALCULATE( [SALARY] - [TAX] ) ) ) Мое подозрение, что в процессе вычислений в наших мерах отрабатывается/вычисляется кучу всего лишнего и потом это фильтруется и отображается только то, что было выбрано в параметрах. Т.е перевести Мультидименшен модель на Табулярную со всеми запросами заказчика (виртуальными мемберами) нам удалось в плане логики (данные схоядтся между старой и новой моделью), но тперь заказчика стал беспокоить Performance, Вернее то, что если выбрать много значений и Period Dimension, выбрать разные группы товаров и категорий, выбрать разных поставщиков - такой репорт отрабатывает очень долго у нас и часто съедат по 50 - 100 Gb памяти и это при условии, что сам куб 30 Gb размером. Буд очень благодарен за любые советы по делу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2019, 17:29 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Igor, >Но уже поздно: заказчик закомандовал табулярку в PaaS, а отказываться от отчетов на Екселе не собирается. Я не перестаю удивляться повторениям попыток "растить кукурузу в Заполярье". MDX клиенты к tabular как и DAX клиенты к multidimensional model это извращение и просадка в производительности на порядок. Имейте яйца в штанах чтобы сказать нет таким заказчикам или топ менеджероте ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.08.2019, 23:52 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Владимир Штепа..чтобы сказать нет таким заказчикам или топ менедж..спонсорам такого не говорят, их только (оператор И ) 1) предупреждают о последствиях 2) предлагают альтернативы т.е. сугубо рекомендательный характер (осторожно, с некоторой настойчивостью) т.к. не забываем что не бизнес работает для IT, а наоборот. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 00:46 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Владимир ШтепаMDX клиенты к tabular как и DAX клиенты к multidimensional model это извращение и просадка в производительности на порядок. Володя, я это знаю :) Просто так случилось, что я уже 2.5 года как дата-саентист, а не BI/OLAP/DW/C# разработчик. Я к этом проекту не имею отношения. И ко мне пришли за советом слишком поздно... Услышав все это, я тоже схватился за голову. Владимир ШтепаИмейте яйца в штанах чтобы сказать нет таким заказчикам или топ менеджероте Вот я бы это сделал. Только меня там не было... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 01:13 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Alex Kork, вот эта мера [SALARY_FC_MTD] почему именно так считается? куча переменных до Return, почему не так, как учат отцы :) https://www.sqlbi.com/articles/optimizing-if-and-switch-expressions-using-variables/ формат в %%, если прямо тяжело, то можно так: при нажатии на слайсер в скрытой сводной таблице минимального размера отложена мера, которая отвечает на вопрос какой формат нужен 0/1, а потом основная сводная таблица просто через условное форматирование применяет нужный формат к своим ячейкам, в этом случае работает только сам Excel почему пишете меры в VS, а не в Tabular Editor, быстрее - не сравнить ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 06:27 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
2. Как это для каждого календаря свои таблицы фактов, дата в фактах от типа календаря разве меняется? Это избыток, в чем именно у Вас затык с разными типами календарей? 3. Расчетные таблицы и расчетные колонки (виртуальные, Related) не сжимаются, проверял на 2016 ssas sp1. Не зря ведь в 2019 VS в расширении SSAS Tabular появился PowerQuery. Материализуйте в источнике данных все расчетные колонки и измерения, при условии что речь не идет о банальном true/false (bit). 4. "Т.е мы в мере считаем и "Current" и "Last Year" и "Male" и "Female" и "MALE+FEMALE"" вот с этим интересно, получается что факты - это некие предрассчитаные сеты для этих значений? т.е. есть отдельная таблица или строки для значения "MALE+FEMALE"? По поводу мер: Все с точности наоборот, сначала определяете что нужно считать (проверка фильтрации пользователя) и лишь потом считаете результат только для одной меры. Тут Вы правы, сами подметили где одна из причин. Почему используете IsFiltered а не hasonefiltred ? Не используйте оператор Sweetch, замените его на If, не очень эстетично но продуктивнее. https://powerpivotpro.com/2013/03/hasonevalue-vs-isfiltered-vs-hasonefilter/ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 09:13 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
вообще не понимаю зачем создали разные меры для MTD, QTD, YTD, сами данные в каком виде лежат? MTD? остаток на начало месяца + движения этого месяца. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 09:20 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Кусок из меры, и так же в остальных: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. Так же проверьте и перепишите меры [SALARY] и [TAX]. Если есть время и возможность, проверьте как будет с MTM нам Ваша структура и данные не известны, возможно выигрыша и не будет, но в таком случае не нужно будет фильтровать, оценка по связи всегда продуктивнее скана (фильтра). И факты не дублируйте для каждого календаря. "DateKey" - Тип данных Date или DateTime, саму таблицу календаря "пометьте как таблица дат" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 10:38 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
"c4ab4bae-95f6-4938-b25a-f0fc97bd8e52" - замените это все на суррогатные ключи. Если взять 6 млрд строк по 36 байт это будет 216 млрд байт, что в переводе на Гб будет 201 Гб. Вся ОЗУ уходит на то что бы хранить ваши бинарники. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 11:45 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Igor.Ko, вот здесь разве не про это? In Analysis Services (SSAS) Tabular, columns are encoded before the compression phase of the processing. This process converts all data to integers (even strings and other data types) since they offer the best performance. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 11:56 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
100ts, по наблюдениям того сколько расходуется памяти когда ключи построены на бинарниках и на интах то что то у табулар не все гладко с кодированием на "лету". Возможно я ошибаюсь. Проверю на данных из 1С (она любит бинарники) и отпишу результат. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 12:09 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
Igor.Ko, да, если можно, я вот через https://www.sqlbi.com/tools/vertipaq-analyzer/ проверяю размер и модели и конкретных полей и размер relation ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 12:17 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
100ts, Не совсем, полученные целочисленные числа (результат Encodinga) будут использоваться в разведке мер, т.е. по факту будут использоваться в отношения между измерениями. Как раз взамен исходного значения (в данном случае GUID). В итоге заменив GUID на свой ключ, производительность в кубе не как не увеличится, но размер модели в памяти сократится но и жрать память он не перестанет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 12:17 |
|
||
|
Tabular SSAS жрет 200 гиг оперативки с Ексель отчетами
|
|||
|---|---|---|---|
|
#18+
IDVT100ts, Не совсем, полученные целочисленные числа (результат Encodinga) будут использоваться в разведке мер, т.е. по факту будут использоваться в отношения между измерениями. Как раз взамен исходного значения (в данном случае GUID). В итоге заменив GUID на свой ключ, производительность в кубе не как не увеличится, но размер модели в памяти сократится но и жрать память он не перестанет. собственно автор темы и жалуется на то что память кто то ест, и в одном из сообщений указывает на использование бинарников в качестве ключа. Коллега 100ts подсказывает что как бы табулар должен все сам заменить. Мое предложение - чисто из спортивного интереса проверить на основании данных из 1С и сравнить модели с бинарниками и с суррогатными ключами инт или биг инт. Посмотрим что получится.... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 22.08.2019, 12:49 |
|
||
|
|

start [/forum/topic.php?fid=49&msg=39851799&tid=1857518]: |
0ms |
get settings: |
10ms |
get forum list: |
12ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
129ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
55ms |
get tp. blocked users: |
1ms |
| others: | 16ms |
| total: | 242ms |

| 0 / 0 |

Извините, этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
... ля, ля, ля ...