|
|
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#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. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. План у него получается следующий (опять таки кусок касающийся этой части запроса): Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. В сумме он выполняется 55 секунд. И происходит это из-за того что GroupAggregate выполняется 327 раз. Соответственно вопрос почему она не материализует GroupAggregate ? Cost же у него запредельный. Estimate маленький. Или у PostgreSQL вообще нет такой возможности как materialize подзапроса и будет проблема в случае: A (маленькая таблица, ключ k0) LJ B (огромная таблица, ключ k0, поле f0 без индекса) ON A.k0 = B.k0 LJ SQ (маленький но долго выполняемый подзапрос с ключом k0) ON SQ.k0 = B.f0 Потому как у нее 2 варианта или высчитать SQ, а затем right join'ить с B что будет очень долго так как придется бежать по B (индекса там напомню нет, да и результат будет большой так что и индекс не поможет), после чего уже hash join'ить с A (план будет очень медленным) или (то что мы видим тут) для всех A, ищем все записи B и для каждой (! так как materialize'а нет) из них выполняем SQ после чего right join'им результат с B (план также будет медленным из-за многочисленного выполнения SQ). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 15:13 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Я вообще правильно понимаю что во втором случае (и собственно в первом), она должна сделать так Hash Right Join Hash Cond SQ.k0 = B.f0 GroupAggregate (допустим группирующий подзапрос с таблицей SQ) Hash Nested Left Join Seq scan A Index scan B on индекс по k0 Index cond : B.k0 = A.k0 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 15:38 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 15:39 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_JunkieNitro_Junkie, Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. Проверил на других запросах, именно так она и должна делать, но почему здесь ее клинит загадка... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 15:58 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, закиньте этот group by в WITH блок и будет вам материализация. Но у меня есть идея почему он не материализует. У вас функция ANYVALUE(1) случайно не volatile? --Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 15:59 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Maxim BogukNitro_Junkie, закиньте этот group by в WITH блок и будет вам материализация. Но у меня есть идея почему он не материализует. У вас функция ANYVALUE(1) случайно не volatile? --Maxim Boguk www.postgresql-consulting.ru Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Я вообще наблюдаю странное явление природы. В приложении запрос показывает такой план, запускаю в pgAdmin план уже нормальный, чудо какое-то... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 16:03 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Воообще совет... в таких ситуациях зачастую проще помочь планировщику и частично зафиксировать нужный вам план через WITH (в тех частях где вам 100% materialize нужен). Ну и понимать что с стандартными настройками базы она только до 8 joins разворачивает/сворачивает а дальше начинается GEQO и угадает он с планом или нет никто не знает. Так что для сложных запросов еще полезно join_collapse_limit/from_collapse_limit поднять слегка. --Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 16:11 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Maxim BogukВоообще совет... в таких ситуациях зачастую проще помочь планировщику и частично зафиксировать нужный вам план через WITH (в тех частях где вам 100% materialize нужен). Ну и понимать что с стандартными настройками базы она только до 8 joins разворачивает/сворачивает а дальше начинается GEQO и угадает он с планом или нет никто не знает. Так что для сложных запросов еще полезно join_collapse_limit/from_collapse_limit поднять слегка. --Maxim Boguk www.postgresql-consulting.ru Проблема в том что 100% materialize тяжеловато угадать. Кстати словил ту же проблему на совсем простом запросе, то есть на GEQO не спишешь: Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. И кстати понял почему в pgAdmin не повторялось. Я когда временную таблицу (t_12) сохранял в постоянную чтобы в pgAdmin запустить, для последней не сделал VACUUM ANALYZE. Тогда postgres думал что записей 1540, а не 327 и план правильный был: Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. Сделал VACUUM ANALYZE для этой t_12 и план стал : Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 16:27 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Хм... Помогает уменьшение join_collapse_limit до 2: Код: plsql 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. 31. 32. 33. 34. 35. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 16:35 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Хотя в общем-то логично что помогает, но управлять порядком join'ов мягко говоря не хочется. И в принципе если взглянуть на 2 плана то у неэффективного cost ниже. Что очень странно с учетом того что она знает что ей нужно 327 loops сделать, и почему-то cost GroupAggregate'а она не умножает на 327 :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 16:41 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, В общем похоже придется CTE делать, но у меня возникла тогда такая мысль. Ведь она CTE считает до выполнения запроса, а можно заставить ее рассчитать статистику по этому CTE ? Потому как подзапросы основное где postgresql ошибается со статистикой... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 16:53 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, 327 повторов уже заложены в cost -> GroupAggregate (cost=50099.52..50101.14 rows=6 width=35) (actual time=171.638..172.528 rows=322 loops=327)" насколько я понимаю. Разница в планах в том что Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. вместо rows=0 получится rows=1 - медленный план станет более быстрым... а в такой ситуации сложно ожидать стабильного поведения планировщика. --Maxim Boguk www.postgresql-consulting.ru ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 16:54 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Maxim BogukNitro_Junkie, 327 повторов уже заложены в cost -> GroupAggregate (cost=50099.52..50101.14 rows=6 width=35) (actual time=171.638..172.528 rows=322 loops=327)" насколько я понимаю. Разница в планах в том что Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. вместо rows=0 получится rows=1 - медленный план станет более быстрым... а в такой ситуации сложно ожидать стабильного поведения планировщика. --Maxim Boguk www.postgresql-consulting.ru Убрал условие c batchUserInvoiceDetail: Код: plsql 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. 31. 32. 33. 34. 35. 36. 37. 38. Хороший план с join_collapse 2: Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 17:07 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk327 повторов уже заложены в cost -> GroupAggregate (cost=50099.52..50101.14 rows=6 width=35) (actual time=171.638..172.528 rows=322 loops=327)" насколько я понимаю. Сделала с CTE: Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. Cost все равно 50к, так что не уверен что loops в неэффективном плане в него включены. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 17:13 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk327 повторов уже заложены в cost Код: plaintext 1. Это просто констатация фактически пройденных циклов (вторая скобка). Планировщик использует предполагаемое кол-во записей. @Nitro_Junkie , а вы могли бы указать версию PostgreSQL и измененную конфигурацию? Статистика свежая на таблицах? Если они временные, то их надо явно анализировать, т.к. они не видны `autovacuum` демону. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 18:06 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorovMaxim Boguk327 повторов уже заложены в cost Код: plaintext 1. Это просто констатация фактически пройденных циклов (вторая скобка). Планировщик использует предполагаемое кол-во записей. @Nitro_Junkie , а вы могли бы указать версию PostgreSQL и измененную конфигурацию? Статистика свежая на таблицах? Если они временные, то их надо явно анализировать, т.к. они не видны `autovacuum` демону. "PostgreSQL 9.3.4, compiled by Visual C++ build 1600, 64-bit" Статистика естественно свежая. Более того когда она не свежая, планировщик лучше работает :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 18:18 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Ах... Вы используете одни и те же алиасы таблиц в разных частях запроса. Я не уверен, к какой `t0` привязывается планировщик в разных частях запроса: Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. Тот факт, что `join_collapse_limit` помогает, делает меня более уверенным. Попробуйте дать уникальные алиасы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 18:41 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorovNitro_Junkie, Ах... Вы используете одни и те же алиасы таблиц в разных частях запроса. Я не уверен, к какой `t0` привязывается планировщик в разных частях запроса: Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. Тот факт, что `join_collapse_limit` помогает, делает меня более уверенным. Попробуйте дать уникальные алиасы. Там в планировщике она подчеркивания добавляет. Но честно попробовал, не помогло естественно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 18:44 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_JunkievyegorovПопробуйте дать уникальные алиасы. Там в планировщике она подчеркивания добавляет. Но честно попробовал, не помогло естественно. А можно увидеть измененный запрос и его планы, с обычными настройками и при `join_collaps_limit=2`? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.02.2015, 18:47 |
|
||
|
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. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. Кривой план: Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. Нормальный план (с join_collapse 2): Код: 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. 31. 32. 33. 34. 35. 36. 37. 38. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.02.2015, 09:44 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Интерсная картинка. При `jcl=2` планировщик увеличивает цену подзапросу `t1` и предпочитает HashJoin, что приводит к нужному эффекту. Почему так происходит понять не могу, в остальном планы одинаковые. Что возвращают такие запросы? Код: sql 1. 2. Вы можете смоделировать ситуацию на другой базе? Скажем, если дампнуть таблицы, создать новый кластер, загрузить таблицы, проанализировать их — какой будет план? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.02.2015, 12:19 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, оторвать бы кому-нибудь руки за такие имена таблиц и полей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.02.2015, 12:20 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorov, "cpu_index_tuple_cost";"0.005";"default" "cpu_operator_cost";"0.0025";"default" "cpu_tuple_cost";"0.01";"default" "random_page_cost";"4";"default" "seq_page_cost";"1";"default" "application_name";"pgAdmin III - ???????????????????? ????????????????";"client" "bytea_output";"escape";"session" "client_encoding";"UNICODE";"session" "client_min_messages";"notice";"session" "DateStyle";"ISO, DMY";"session" "default_text_search_config";"pg_catalog.russian";"configuration file" "lc_messages";"Russian_Russia.1251";"configuration file" "lc_monetary";"Russian_Russia.1251";"configuration file" "lc_numeric";"Russian_Russia.1251";"configuration file" "lc_time";"Russian_Russia.1251";"configuration file" "listen_addresses";"*";"configuration file" "log_destination";"stderr";"configuration file" "log_line_prefix";"%t ";"configuration file" "log_timezone";"Europe/Bucharest";"configuration file" "logging_collector";"on";"configuration file" "max_connections";"100";"configuration file" "max_locks_per_transaction";"1000";"configuration file" "max_stack_depth";"2048";"environment variable" "port";"5432";"configuration file" "shared_buffers";"16384";"configuration file" "TimeZone";"Europe/Bucharest";"configuration file" "work_mem";"524288";"configuration file" Сча попробую dump restore. Но меня в принципе волнует вопрос почему при подсчете cost'а плана, СУБД не учитывает что при Nested Loop нужно несколько раз выполнять GroupAggregate. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.02.2015, 12:35 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
Nitro_Junkie, Да, я понимаю про NestedLoops. Если вы сможете изолированно воспроизвести ситуацию, то можно написать разработчикам (я могу помочь). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.02.2015, 12:40 |
|
||
|
NESTED LOOP и GroupAggregate
|
|||
|---|---|---|---|
|
#18+
vyegorovNitro_Junkie, Да, я понимаю про NestedLoops. Если вы сможете изолированно воспроизвести ситуацию, то можно написать разработчикам (я могу помочь). Изолировать постараюсь в любом случае, и если он будет тривиальным запостить багрепорт, но пока мы прорабатываем вопрос решения проблемы в общем случае - самим материализовать подзапросы, если "что-то пошло не так". Можно конечно через CTE это делать, но там статистика плывет. Просто разработчики конечно может и помогут, но вряд ли они изменят, то что когда планировщик про Aggregate чего-то не знает, тупо лепит ему статистику 200, после чего начинаются чудеса с nested loop'ами. Плюс проблему надо решать уже :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.02.2015, 12:52 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=38883241&tid=1998148]: |
0ms |
get settings: |
8ms |
get forum list: |
18ms |
check forum access: |
3ms |
check topic access: |
4ms |
track hit: |
169ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
68ms |
get tp. blocked users: |
1ms |
| others: | 225ms |
| total: | 506ms |

| 0 / 0 |
