|
|
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_JunkieПлюс проблему надо решать уже :(А если добавить скобочки, чтобы явно задать порядок сортировки? Код: sql 1. 2. 3. 4. 5. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.02.2015, 15:33 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorovNitro_JunkieПлюс проблему надо решать уже :(А если добавить скобочки, чтобы явно задать порядок сортировки? Код: sql 1. 2. 3. 4. 5. Это уже похоже на перестановку кроватей. Тем более что явный порядок сортировки и задается уменьшением join_collapse_limit (как мы выяснили это как раз помогает). Вопрос почему она сама неправильно определяет порядок. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 09:27 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_JunkieЭто уже похоже на перестановку кроватей. Тем более что явный порядок сортировки и задается уменьшением join_collapse_limit (как мы выяснили это как раз помогает). Вопрос почему она сама неправильно определяет порядок. `join_collapse_limit` ограничивает планировщик в перестановке JOIN конструкций. В данном запросе эффект одинаковый (я полагаю?), однако может быть так, что уменьшение `join_collapse_limit` приведет к худшему плану. А скобочки позволяют точечно вправить мозг планировщику. Я согласен — почему “она сама неправильно определяет порядок” гораздо интереснее. Нужен тест кейс. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 10:17 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorov, В общем минимальное что смог пока найти: Код: 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. Код: 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. Второй внутренний подзапрос все не получается убрать. Соответственно проблема когда внутри LAST есть ORDER BY, если его убрать все становится хорошо: Код: 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. При этом что забавно агрегация идет в цикле. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 10:41 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Вообще конечно странно что во втором плане loops = 327 только в HashAggregate, а в первом идет вплоть до Index scan. При этом на самом деле разница только в том что в первом случае GroupAggregate с sort'ом, а во втором HashAggregate. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 10:51 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Собственно видимо в этом и проблем HashAggregate выполняется за 0,57 миллисекунды, а GroupAggregate за 122 миллисекунды. Хотя алгоритмическая сложность у них одинаковая и cost'ы тоже :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 10:54 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Собственно если сделать enable_sort TO off, который увеличит cost Group Aggregate до бесконечности все тоже становится ОК. Код: 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. 30. Но не хочется включать enable_sort на весь сервер. :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 11:14 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Мне кажется, что планировщик неверно оценивает агрегатную функцию с `ORDER BY`. Поиграться бы с этим случаем. Вы какой-то дамп можете предоставить? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 11:30 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorovNitro_Junkie, Мне кажется, что планировщик неверно оценивает агрегатную функцию с `ORDER BY`. Поиграться бы с этим случаем. Вы какой-то дамп можете предоставить? Агрегатная функция в плане вообще не показывается. Может вы знаете где еще можно информацию достать. Но вообще что интересно у Hash Join в обоих планах и actual time и rows и cost одинаковые, но почему у HashAggregate, который идет строкой выше actual time 0.51, то есть деленное на loops, а у GroupAggregate нет - загадка. То есть я даже не могу догнать как именно он выполняет эти планы, не то что почему он их так оценивает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 11:43 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Агрегатная функция выражается в узлах `GroupAggregate` (который требует отсортированных данных) или `HashAggregate`, который быстрый и потому предпочтительней. Добавляя `ORDER BY` в агрегатную функцию вы задаете порядок, который требует сортировку. Ну и при таком раскладе можно использовать `GroupAgg`, т.к. данные уже отсортированы. Но планировщик (мне кажется) что-то не учитывает и запихивает `Sort`+`GroupAgg` в цикл, что выходит очень дорого. И вот этот момент хотелось бы прояснить у разработчиков. (От сортировки можно было бы избавиться через индекс, но у вас используются колонки из разных таблиц...) Общее время потраченное на узел считается как `actual time` * `loops`. Хотя на самом деле во время исполнения регистрируется общее время, а потом делиться на кол-во проходов. Тоже самое и для кол-ва реальных записей возвращенных узлом. Это иногда приводит к тому, что записи показывается как `0`, если некоторые проходы были безрезультатны. В случае с `HashAggregate` умножаем 0.483 на 327 и получаем 157ms, что похоже на общее время исполнения. Для `GroupAggregate` умножаем 122.150 (что уже почти равняется общему времени для `HashAgg`) на 327 и получаем 39943.05 (40 секунд). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 12:40 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorovNitro_Junkie, Агрегатная функция выражается в узлах `GroupAggregate` (который требует отсортированных данных) или `HashAggregate`, который быстрый и потому предпочтительней. Добавляя `ORDER BY` в агрегатную функцию вы задаете порядок, который требует сортировку. Ну и при таком раскладе можно использовать `GroupAgg`, т.к. данные уже отсортированы. Но планировщик (мне кажется) что-то не учитывает и запихивает `Sort`+`GroupAgg` в цикл, что выходит очень дорого. И вот этот момент хотелось бы прояснить у разработчиков. (От сортировки можно было бы избавиться через индекс, но у вас используются колонки из разных таблиц...) Общее время потраченное на узел считается как `actual time` * `loops`. Хотя на самом деле во время исполнения регистрируется общее время, а потом делиться на кол-во проходов. Тоже самое и для кол-ва реальных записей возвращенных узлом. Это иногда приводит к тому, что записи показывается как `0`, если некоторые проходы были безрезультатны. В случае с `HashAggregate` умножаем 0.483 на 327 и получаем 157ms, что похоже на общее время исполнения. Для `GroupAggregate` умножаем 122.150 (что уже почти равняется общему времени для `HashAgg`) на 327 и получаем 39943.05 (40 секунд). Попытался поиграться с планами, но в других случаях планировщик всегда вставляет, что-то типа следующего: [SQL] " -> Materialize (cost=6164744.96..6164838.15 rows=327 width=16) (actual time=80.627..80.630 rows=96 loops=327)" " -> Subquery Scan on t1 (cost=6164744.96..6164836.52 rows=327 width=16) (actual time=26364.901..26365.295 rows=96 loops=1)" " -> GroupAggregate (cost=6164744.96..6164833.25 rows=327 width=24) (actual time=26364.900..26365.286 rows=96 loops=1)" [/SQL] Почему он здесь этого не делает неясно. Более того я тогда вообще не понимаю пункта плана Materialize. Ведь в правильном исходном плане Materialize'а нет, но де-факто он происходит, как видим Hash Join идет 1 раз. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 13:07 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, `Materialize` значит, что планировщик понимает, что одни и те же данные будут сканироваться некоторое число раз, и находит, что ему дешевле сохранить результат под-плана, а не вычислять его каждый раз заново. Естественно, такое возможно, если под-план всегда возвращает одинаковый результат. И я полагаю, что это стало возможным потому, что вы убрали функцию `ANYVALUE()` (как ранее указывал Максим). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 14:23 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorovNitro_Junkie, `Materialize` значит, что планировщик понимает, что одни и те же данные будут сканироваться некоторое число раз, и находит, что ему дешевле сохранить результат под-плана, а не вычислять его каждый раз заново. Естественно, такое возможно, если под-план всегда возвращает одинаковый результат. И я полагаю, что это стало возможным потому, что вы убрали функцию `ANYVALUE()` (как ранее указывал Максим). Тогда почему "в правильном исходном плане Materialize'а нет, но де-факто он происходит, как видим Hash Join идет 1 раз" ANYVALUE по моим наблюдениям никак не влияет на планы. Что он есть его нет... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 15:01 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_JunkieТогда почему "в правильном исходном плане Materialize'а нет, но де-факто он происходит, как видим Hash Join идет 1 раз" Я не знаю. Предполагаю, что особенности работы с хэш-таблицей позволяют построить ее один раз (на основании результатов HashJoin) и затем просто возвращать агрегированные данные. Потому HashJoin loops=1, но вышестоящий HashAggregate loops=327. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.02.2015, 16:28 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorovNitro_JunkieТогда почему "в правильном исходном плане Materialize'а нет, но де-факто он происходит, как видим Hash Join идет 1 раз" Я не знаю. Предполагаю, что особенности работы с хэш-таблицей позволяют построить ее один раз (на основании результатов HashJoin) и затем просто возвращать агрегированные данные. Потому HashJoin loops=1, но вышестоящий HashAggregate loops=327. а для сортировки ее надо 327 раз джойнить? ммм ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.02.2015, 01:26 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=38884812&tid=1998148]: |
0ms |
get settings: |
7ms |
get forum list: |
14ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
46ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
62ms |
get tp. blocked users: |
1ms |
| others: | 197ms |
| total: | 343ms |

| 0 / 0 |
