| Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
| Все форумы / OLAP и DWH |
![]() |
||
| Топик располагается на нескольких страницах: [1] 2 вперед Ctrl→ все |
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
в скрипте куба есть следующаяя формулаCREATE SET CURRENTCUBE.[Current Date Set] AS Tail(Exists([Calendar].[Date].[Date].Members, , 'Snapshot'), 1); При выполнении этого вычисления, почуму то производится скан всех разделов куба, хотя для каждого раздела аккуратно задан слайс по измерению времени, аттрибуту месяц [Calendar].[Month] Возникает собственно вопрос, в состоянии ли оптимизатор сообразить, что то если запросили Tail(Set, 1), а сет то упорядоченный, так как это уровень измерения, то не надо сканить все подряд, а надо начать поиск с правильного конца, в правильном разделе. Так как в каждом разделе задан слайс, то движек должен знать, с какого раздела начать поиск и так как запрошено конечное количество элементов (Tail(Set, 1)), когда его прекратить. Интересно это баг SSAS или оптимизатор до этого еще не дозрел и надо самому изголяться. |
| 15 дек 07, 19:04 [5053604] Ответить | Цитировать Сообщить модератору | |
|
Mosha Member Откуда: Сообщений: 1272 |
Такой оптимизации в AS нет. Моша ---------------------------------------------------- This posting is provided "AS IS" with no warranties, and confers no rights |
| 16 дек 07, 01:48 [5054488] Ответить | Цитировать Сообщить модератору | |
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
Даже в 20** не будет? А что же делать? Изголяться? Жаль :-( А в реляционном движке есть. Там партиционирующая функция принимается во внимание оптимизатором. |
||
| 16 дек 07, 02:31 [5054592] Ответить | Цитировать Сообщить модератору | |||
|
Mosha Member Откуда: Сообщений: 1272 |
Переписать MDX так чтобы не использовал функцию Exists по всем датам. При Ваших знаниях MDX, это возьмёт 5 минут.
А вот этого сравнения я бы не стал делать. В реляционном движке оптимизатор запросов конечно более мощный чем в AS, но как раз по работе с разделами/partitions, AS гораздо сильнее SQL Servera. Моша ---------------------------------------------------- This posting is provided "AS IS" with no warranties, and confers no rights |
||||
| 16 дек 07, 22:55 [5055709] Ответить | Цитировать Сообщить модератору | |||||
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
Моша, либо Вы меня очень переоцениваете , либо мы друг друга не поняли :-(. Речь идет не о использовании или неиспользовании exists, а о том, как добится чтобы не читались все разделы группы мер. Даже если написать Tail(Exists([Calendar].[Year].[Year].Members, , 'Snapshot'), 1); и в измерении всего 5 лет, то все равно просходит чтение всех разделов. Почему? Даже если заменить Exists на NonEmpty, природа выполнения запроса отстается. Результаты кешируются хорошо, но на холодном кеше это черепаха :-(
И в чем же сила? В том, что происходит скан всех разделов года, когда спрашивается, а есть ли вообще данные в году, а не достаточно ли остановить чтение, когда в каком либо разделе обнаруженны данные? Напомню, аггрегатов в кубе нет. |
||||||||
| 17 дек 07, 00:31 [5055866] Ответить | Цитировать Сообщить модератору | |||||||||
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
Моша, знания MDX мне наверное надо еще развивать и развивать, поэтому решаю проблему по-своему ставлю зарубки в группе мер "календарь" - эта группа мер читается влет. А вот что Вы имели в виду, намекая, что там мне делов на 5 минут, остается незвестным. |
||
| 17 дек 07, 02:26 [5055951] Ответить | Цитировать Сообщить модератору | |||
|
Mosha Member Откуда: Сообщений: 1272 |
Да, разумеется, речь идёт именно об этом. Я просто хотел сказать что Exists или NonEmpty по всем датам являются слишком прямой инструкцией для движка. Переписать MDX так чтобы он возвращал нужный результат и затрагивал только последний раздел несложно, у меня даже в книжке "Fast Track to MDX" есть пример для очень похожей ситуации. Конечно, встаёт вопрос как переписать MDX так, чтобы этот последний раздел читался как можно меньше раз. При помощи небольшого преобразования можно свести к максимум двум разам, и при помощи ещё одного трика к максимум одному разу, т.е. оптимальное решение. Оставляю это как упражнение для читателя, но если кому то интересно, то могу опубликовать решение. В споры "какой движок круче" я вступать не хочу, и жалею что сам поднял эту тему. Пусть каждый останется при своём мнении.
Да, безусловно так будет быстрее всего. А ещё быстрее просто где-то держать саму последнюю дату. И ещё быстрее прописывать её внутри самого MDX Script. Впрочем это мы уже обсуждали. Баланс между скоростью соединения с кубом и гибкостью автоматизации. Моша ---------------------------------------------------- This posting is provided "AS IS" with no warranties, and confers no rights |
||||
| 17 дек 07, 03:57 [5055970] Ответить | Цитировать Сообщить модератору | |||||
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
Моша, да вопрос то вообще, как определить последний раздел с помощью MDX?
Ну хоть ту наши мнения не расходятся. |
||||||
| 17 дек 07, 04:24 [5055977] Ответить | Цитировать Сообщить модератору | |||||||
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
Как я еще выяснил, решению проблемы низкой производительности из-за скана разделов, хорошо помогает наличие целевых аггрегатов, только вот "из лююбви к искуссву" хотелось все таки решить проблему чистым мдх. |
| 17 дек 07, 20:55 [5060195] Ответить | Цитировать Сообщить модератору | |
|
Mosha Member Откуда: Сообщений: 1272 |
Ну навскидку, вот такое должно читать только последний раздел и только один раз. Пример приведён для Adventure Works, где разделы сделаны по годам.create member CurrentCube.LastYearIndex as iif( IsEmpty(Aggregate(Descendants([Date].[Calendar], [Date].[Calendar].[Date]), [Measures].[Internet Sales Amount])), [Date].[Calendar Year].PrevMember, Rank([Date].[Calendar Year].CurrentMember, [Date].[Calendar Year].[Calendar Year]) ) create set CurrentCube.LastYear as [Date].[Calendar Year].[Calendar Year].Item((LastYearIndex, [Date].[Calendar Year].LastChild)-1) create set CurrentCube.LastDate as Tail(NonEmpty([Date].[Date].[Date].MEMBERS, (LastYear, [Measures].[Internet Sales Amount])), 1) Моша ---------------------------------------------------- This posting is provided "AS IS" with no warranties, and confers no rights |
| 17 дек 07, 21:15 [5060247] Ответить | Цитировать Сообщить модератору | |
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
Натурные испытания показывают, что читается не только последний 4-й раздел, но и 1-й и 2-й? :-( Моша, Вы бы не могли объяснить, как работает IIF в вашей формуле. Точнее к какому типу и как приводится iif (bool, Member, Scalar). Как же Member приводится к скаляру??? |
||
| 18 дек 07, 00:44 [5060629] Ответить | Цитировать Сообщить модератору | |||
|
Mosha Member Откуда: Сообщений: 1272 |
Нет, читается только последний раздел. Вопрос "как мембер приводится к скаляру" я не очень понял, в смысле что приводится точно так же как и всегда, например, если написано Sales - Cost, то и Sales и Cost оба мемберы, и оба приводятся к скалярам (через метод .Value чтобы уж совсем быть точным). А что в моей формуле отличается ? Моша ---------------------------------------------------- This posting is provided "AS IS" with no warranties, and confers no rights |
| 18 дек 07, 01:30 [5060657] Ответить | Цитировать Сообщить модератору | |
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
Может у меня велозавод левый. переписал под свою базу. Летает. Большое Вам спасибо. Так как у меня куб разбит по месяцам, то переписал вашу формулу под LastMonthIndex.
Да просто непривычно очень. Например IIF(логическое выражение, [Date].[Calendar Year].PrevMember, Rank([Date].[Calendar Year].CurrentMember, [Date].[Calendar Year].[Calendar Year]) ) преобразование происходит по принципу IIF(логическое выражение, [Date].[Calendar Year].PrevMember.Value, Rank([Date].[Calendar Year].CurrentMember, [Date].[Calendar Year].[Calendar Year]) ) С Rank понятно. он скаляр возвращает. Теперь вопрос к какому скаляру преобразуется [Date].[Calendar Year].PrevMember.Value??? Точно так же меня смущает конструкция (LastYearIndex, [Date].[Calendar Year].LastChild) из Item((LastYearIndex, [Date].[Calendar Year].LastChild)-1) Было очень любезно с Вашей стороны, прокомментировать подобную практику написания MDX. |
||||
| 18 дек 07, 02:28 [5060673] Ответить | Цитировать Сообщить модератору | |||||
|
Mosha Member Откуда: Сообщений: 1272 |
Это рекурсия. Вычисление будет сдвигаться по времени назад пока не найдёт непустой год. Подробнее, у меня во втором издании Fast Track to MDX есть целая глава которая этот механизм обьясняет в деталях. И пример там очень похожий на этот.
Это тупл, который говорит: Вычислить индекс начиная с последнего года. Т.е. LastChild устанавливает нас на последний год, а LastYearIndex начинает рекурсивно от него двигаться назад (см. выше). Интересно что никто не спросил почему в условии IIF используется проверка IsEmpty(Aggregate(Descendants([Date].[Calendar], [Date].[Calendar].[Date]), [Measures].[Internet Sales Amount])) вместно казалось бы более очевидного IsEmpty([Measures].[Internet Sales Amount]). А ведь это не просто так... Моша ---------------------------------------------------- This posting is provided "AS IS" with no warranties, and confers no rights |
||||
| 18 дек 07, 21:50 [5065789] Ответить | Цитировать Сообщить модератору | |||||
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
уже пошел на амазон за вашей книжкой, так как думаю, что это нигде больше не описано. Или все таки в каком то вашем блоге есть систематическое описание рекурсии.
Да тут вся тема не просто так. А что касается аггрегата, то я не вижу разницы ни в результате, ни в скорости, ни в плане выполнения запроса, если выкинуть aggregate и оставить меру. |
||||||||
| 19 дек 07, 01:20 [5066218] Ответить | Цитировать Сообщить модератору | |||||||||
|
Mosha Member Откуда: Сообщений: 1272 |
Вот кстати по этому адресу вся эта дискуссия суммаризирована (на английском языке) http://sqlblog.com/blogs/mosha/archive/2007/12/18/mdx-and-partitioning.aspx Моша ---------------------------------------------------- This posting is provided "AS IS" with no warranties, and confers no rights |
| 19 дек 07, 10:08 [5066671] Ответить | Цитировать Сообщить модератору | |
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
Я думаю, что рановато будет - подводить черту до того, как не будет упомянуто, что мера типа LastNonEmpty страдает тем недостатком, что сканит все разделы участвующие в слайсеselect [Measures].[Amount End_LastNonEmpty] on 0 from [Inventory] select [Measures].[Amount End_LastNonEmpty] on 0, [Calendar].[YQMD].[Year].&[2006] on 1 from [Inventory] select [Measures].[Amount End_LastNonEmpty] on 0, [Calendar].[YQMD].[Quarter].&[200603] on 1 from [Inventory] Я думаю, что серийный движек SSAS должен быть испавлен от этого недостатка, на радость всех его пользователей. |
| 19 дек 07, 12:53 [5067843] Ответить | Цитировать Сообщить модератору | |
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
Для тех кто не читает Мошины блоги. Как-раз в блоге очень подробно и доходчиво Моша излагает, а что же сущности там "не просто так..." |
||
| 19 дек 07, 21:00 [5071393] Ответить | Цитировать Сообщить модератору | |||
|
RegisteredUser Member Откуда: Сообщений: 287 |
Столкнулся с аналогичной проблемой в партишенах. (решение проблемы описаны тут: MDX and partitioning) Но в нашем случае есть небольшое отличие: наши партишены порублены на неделям ([46-08] - это значит 46 неделя 2008 года) и есть MDX, который выполнясь сканит все партишены, что есть плохо. Прошу подсказать, что надо поменять в данном ниже MDX, чтобы избавится от странного поведения?
SELECT
NON EMPTY
{ VISUALTOTALS({
[Network].[RegionC].[National]
, [Network].[RegionC].[Region].&[Northeast]
})
} ON COLUMNS
, NON EMPTY
{ VISUALTOTALS({
[Measures].[Composite Block %]
, [Measures].[Trigger %]
})
} ON ROWS
FROM [Trending]
WHERE ( ( [Time].[Year - Day FMT].[Week Year].&[2008].&[46-08] ) )
|
| 12 ноя 08, 11:59 [6427863] Ответить | Цитировать Сообщить модератору | |
|
RegisteredUser Member Откуда: Сообщений: 287 |
Коллеги! Большая просьба ответить на мой вопрос выше. Ну или хотя бы сказать почему SSAS читает все пртешены вместо того, чтобы обрашаться напрямую к нужному? У нас идет солидная потеря производительности на этих запросах и юзера постоянно хнычут в саппорт. |
| 13 ноя 08, 11:39 [6433570] Ответить | Цитировать Сообщить модератору | |
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
[quot RegisteredUser]Столкнулся с аналогичной проблемой в партишенах. (решение проблемы описаны тут: MDX and partitioning) Как раз там они просто написаны на английском, а изначально они описаны тут, см. крайний Мошин пост. |
| 13 ноя 08, 19:32 [6437777] Ответить | Цитировать Сообщить модератору | |
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
RegisteredUser, а вы можете воссоздать проблему на Adventure Works? То как написан ваш запрос, за исключением VisualTotals, повендение кооторого был для меня всегда загадкой, указвает на то, что сканирования разделов не должно просходить не при каких условиях. А так сканирует? SELECT
{[Network].[RegionC].[National], [Network].[RegionC].[Region].&[Northeast]} ON COLUMNS,
{[Measures].[Composite Block %], [Measures].[Trigger %]} ON ROWS
FROM [Trending]
WHERE [Time].[Year - Day FMT].[Week Year].&[2008].&[46-08][Measures].[Composite Block %], [Measures].[Trigger %] Это вычисляемые меры? А если из заменить какой нить физ мерой, скан происходит? |
| 13 ноя 08, 19:39 [6437799] Ответить | Цитировать Сообщить модератору | |
|
RegisteredUser Member Откуда: Сообщений: 287 |
сегодня все проверю и отпишусь о резалте. пасиба за помощь. |
||
| 14 ноя 08, 11:16 [6439607] Ответить | Цитировать Сообщить модератору | |||
|
RegisteredUser Member Откуда: Сообщений: 287 |
Ситуация такова: 1. если запускать запросы через сервис который генерит отчеты, то скан партишенов идет всегда НО если запускать MDX запросы через менеджмент студию или MDXStudio, то вроде бы все работает нормально 2. резалт запросов с VisualTotals и без него - разный (но на это внимания не обращаем пока) 3. [Measures].[Composite Block %],[Measures].[Trigger %] - это calculated member CREATE MEMBER CURRENTCUBE.[MEASURES].[Composite Block %] AS [Measures].[CompositeBlockR]*100, FORMAT_STRING = "#,0.00", VISIBLE = 1; CREATE MEMBER CURRENTCUBE.[MEASURES].[Trigger %] AS [Measures].[TriggerR]*100, FORMAT_STRING = "#,0.00", VISIBLE = 1; Итого: получается, что из менеджмент студию или MDXStudio нельзя точно смоделировать ситиуацию которая происходит на реальном сервере. а на реальном сервере скан есть и профайлер это показывает. Вот привожу на всякий случай статистику по MDXStudio для запросов с и без VisualTotals и с очисткой и без очистки кеша -= MDX + VisualTotals + clear cashe =- Time : 5 sec 875 ms Calc covers : 168 Cells calculated : 256 Sonar subcubes : 245 SE queries : 86 Cache hits : 135 Cache misses : 72 Cache inserts : 24 Cache lookups : 207 Memory Usage KB : 3808 -= MDX + VisualTotals БЕЗ clear cashe =- Time : 62 ms Calc covers : 168 Cells calculated : 256 Sonar subcubes : 203 SE queries : 57 Cache hits : 155 Cache misses : 19 Cache inserts : 0 Cache lookups : 174 Memory Usage KB : 0 -= MDX без VisualTotals + clear cashe =- Time : 10 sec 359 ms Calc covers : 168 Cells calculated : 128 Sonar subcubes : 245 SE queries : 86 Cache hits : 173 Cache misses : 72 Cache inserts : 24 Cache lookups : 245 Memory Usage KB : 13168 -= MDX без VisualTotals БЕЗ clear cashe =- Time : 31 ms Calc covers : 56 Cells calculated : 128 Sonar subcubes : 29 SE queries : 0 Cache hits : 16 Cache misses : 0 Cache inserts : 0 Cache lookups : 16 Memory Usage KB : 0 |
| 14 ноя 08, 18:35 [6443337] Ответить | Цитировать Сообщить модератору | |
|
Владимир Штепа Member Откуда: Hannover Сообщений: 5929 |
а кто же кроме вас знает как этот сервис коннектится и как запросы выполняет? |
||
| 14 ноя 08, 18:46 [6443394] Ответить | Цитировать Сообщить модератору | |||
| Топик располагается на нескольких страницах: [1] 2 вперед Ctrl→ все |
| Все форумы / OLAP и DWH | ![]() |
|