|
|
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Доброго дня! В целях быстродействия функции решил оптимизировать в ней запрос: сменить медленные подзапросы на LEFT JOIN. вот исходный запрос: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. перешел на LEFT JOIN: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. как и ожидалось, результат получаем одинаковый. Далее для сравнения запустил выполнение обоих запросов в цикле на 10000 повторений. Результат: 1-й запрос: QUERY PLAN Result (cost=0.00..0.26 rows=1 width=0) (actual time=752.993..834.105 rows=50000 loops=1) Total runtime: 894.151 ms 2-й запрос: QUERY PLAN Result (cost=0.00..0.26 rows=1 width=0) (actual time=875.821..957.876 rows=50000 loops=1) Total runtime: 1017.922 ms чем же запрос с использованием LEFT JOIN лучше запроса с использованием подзапросов, если он медленнее выполняется? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.01.2013, 18:18 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalich, Потому что сильно напоминает анекдот: "Мне Рабинович в коридоре напел". Приведите нормальный план запроса, чтобы были видны какие индексы используются и используются ли вообще. "Как и ожидалось..." -- если Вы намекаете на то, что PostgreSQL не годится для оптимальных запросов, то специально для Вас ответ: "таки да". Вы в обеих запросах используете одно и то же условие: cl.s_id = 1 AND cl.expiration_time IS NULL. Только в первом запросе дополнительные данные вытягиваются только из отобранных данных (то есть после фильтра), а во втором фильтр применяется уже после того, как туева хуча дополнительных данных присоединена к результатам запроса. Вот почему второй вариант хуже. При этом совершенно не ясна судьба фильтрации: есть ли индекс по cl.s_id, применяется ли он (по соображениям селективности), может быть есть смысл применить условный фильтр. Приведите нормальный план запроса. Сразу можете привести долю записей с cl.s_id = 1 из общей массы, распределение по другим значениям. А так же в комбинации с cl.expitation_time. Это чтобы прикинуть возможности индекса. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.01.2013, 19:08 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
ну, спасибо! Сразу 2 удовольствия в одном: и ответ и анекдот для запроса: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. план: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. для запроса: Код: plsql 1. 2. 3. 4. 5. 6. 7. план: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.01.2013, 19:47 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalich, Так и есть! Seq Scan on ""CLINICS"" cl (cost=0.00..1.09 rows=1 width=20)" Filter: ((""EXPIRATION_TIME"" IS NULL) AND (""SETTLEMENT_ID"" = 1))" В обеих запросах это не вызывает совершенно никаких эмоций. С учетом предыдущих предложений обратить внимание на построение индекса. Вам на будущее: всегда приводите реальные запросы с которыми работаете. Потому что в 95% случаев выясняется, что запрос был другим, а вся беседа была зря. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.01.2013, 19:57 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalich, вы приводите а)результаты explain analyze а не explain б)На рабочих данных а не на пустой таблице (то что вы привели) планы запросов ЗАВИСЯТ от данных в таблице и смотреть планы на пустых таблицах смысла ровно 0. Если возращается 50000 строк в запросе то оба варианта будут небыстрыми... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2013, 02:15 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Привожу с нагруженной таблицей в 100008 записей: 1. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. QUERY PLAN: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 2. Код: plsql 1. 2. 3. 4. 5. 6. 7. QUERY PLAN: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. сама таблица: Код: 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. 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. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2013, 14:54 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalich, Пожалуйста, приведите результат запросов: Код: sql 1. 2. 3. 4. 5. 6. Код: sql 1. 2. 3. 4. 5. 6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2013, 15:26 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
1. Код: plsql 1. 2. 3. 4. 5. результат: Код: sql 1. 2. 3. 4. 2. Код: plsql 1. 2. 3. 4. 5. результат: Код: sql 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2013, 16:44 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
с "EXPIRATION_TIME" IS NULL маловато конечно данных, по полю "SETTLEMENT_ID" данные отличаются. Возможно такие данные не показательны, могу по-разнообразней таблицу заполнить: с множеством различных "SETTLEMENT_ID" и чтобы "EXPIRATION_TIME" IS NULL было по-больше. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2013, 16:49 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalich, пока у вас в присоединяемых таблицах по 1-2-5 записям план с subrequests вероятнее всего будет быстрее... я бы попробовал поиграть с cpu_tuple_cost/random_page_cost для получения другого плана но принципиально быстрее не будет... просто изза того что запрос на 50000 строк быстрым быть не может просто по своим свойствам... попробуйте выполнить set enable_material to 0; и заново выполнить explain analyze запроса с left join пришлите результаты они очень интересны будут... вторым этапом попробовать еще сделать set enable_nestloop to 0; и тоже сделать explain analyze если какая то из этих 2х версий будет заметно быстрее можно будет подумать о том в какую стороно крутить *_cost для получения более быстрого плана... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2013, 16:50 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
выполнил set enable_material to 0; затем заново выполнил explain analyze запроса с left join: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. Шайтан! время выполнения сократилось с 2604.619 ms до 745.953 ms! А что собственно произошло после выполнения set enable_material to 0; в двух словах? далее выполняю set enable_nestloop to 0; затем заново explain analyze запроса с left join: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. время выполнения: "Total runtime: 748.315 ms". P.S. Причем на время выполнение запроса с подзапросами эти магматические заклинания не подействовали: было: 1651.062 ms, стало: 1646.203 ms. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.01.2013, 17:52 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalichвыполнил set enable_material to 0; затем заново выполнил explain analyze запроса с left join: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. Шайтан! время выполнения сократилось с 2604.619 ms до 745.953 ms! А что собственно произошло после выполнения set enable_material to 0; в двух словах? далее выполняю set enable_nestloop to 0; затем заново explain analyze запроса с left join: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. время выполнения: "Total runtime: 748.315 ms". P.S. Причем на время выполнение запроса с подзапросами эти магматические заклинания не подействовали: было: 1651.062 ms, стало: 1646.203 ms. а если вы еще set work_mem to '16Mb'; поставите еще быстрее будет (~500ms) достаточно сочетания enable_material to 0 и повышенного work_mem а что сделали - запретили использовать неудачный метод соединения таблиц для запроса... я потом поиграю с этим всем и попробую bug-report/test-case разработчикам отправить... не первый раз вижу когда план с материализацией тормозит... что то они с его ценой намудрили. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 01:29 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, да, с set work_mem to '16Mb' еще быстрее отработало: "Total runtime: 687.393 ms" В результате производительность возросла в 3,8 раза. Видимо "set enable_material to 0;" и "set work_mem to '16Mb' " нужно выполнять каждый раз, как коннектишься к базе, т.к. при выходе настройка слетает и все возвращается на круги своя. А за помощь однозначно всем спасибо! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 09:58 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalich, Эти параметры можно установить раз и навсегда в postgresql.conf (enable_material в разделе Planner Method Configuration). (Может, там еще что-нибудь можно поднастроить). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 10:23 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Все здОрово: параметры выставил, на запрос с "explain analyze" полюбовался, порадовался скорости выполнения. Но возник еще один, возможно глупый вопрос: "explain analyze" снимаю, чтобы работать с реальными данными, и вижу, что настройки: "set enable_material to 0;" и "set work_mem to '16Mb' " без "explain analyze" уже не действуют. Для запроса: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Суммарное время выполнения запроса: 5032 ms (он же с "explain analyze": 694.387 ms). Для запроса: Код: plsql 1. 2. 3. 4. 5. 6. 7. Суммарное время выполнения запроса: 4968 ms (он же с "explain analyze": 1642.155 ms). P.S. других настроек не трогал, данные в таблице не менял. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 11:02 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalich чем же запрос с использованием LEFT JOIN лучше запроса с использованием подзапросов, если он медленнее выполняется? Время выполнения запроса не является критерием качества запроса, и, как ни странно, даже не является критерием производительности запроса. Приводи io. По сути же — что в лоб, что по лбу — запросы одинаковы, они даже возможно дают один и тот же план, и выполняются одинаковыми образом. А то, что ты видишь— просто случайные отклонения, вызванные сторонними причинами. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 11:11 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalich, либо в .config, либо Код: plsql 1. либо при старте каждого коннекта клиента Код: plsql 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 11:14 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
/\/\/\/\/\/\/\ Вы в обеих запросах используете одно и то же условие: cl.s_id = 1 AND cl.expiration_time IS NULL. Только в первом запросе дополнительные данные вытягиваются только из отобранных данных (то есть после фильтра), а во втором фильтр применяется уже после того, как туева хуча дополнительных данных присоединена к результатам запроса. Вот почему второй вариант хуже. Предположения о порядке вычисления элементов запроса более чем смелые. Для тех, кто не понимает сарказм, скажу прямо: они неверные. Так же, как и оценки качества PG как субд. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 11:15 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
MasterZivПредположения о порядке вычисления элементов запроса более чем смелые. Пожалуйста, укажите где можно ознакомиться с порядком вычисления, чтобы предположения превратились в уверенность. Какой-нибудь RTFM, желательно официальный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 11:22 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
/\/\/\/\/\/\/\/\/\MasterZivПредположения о порядке вычисления элементов запроса более чем смелые. Пожалуйста, укажите где можно ознакомиться с порядком вычисления, чтобы предположения превратились в уверенность. Какой-нибудь RTFM, желательно официальный. Нигде нельзя, порядка вычисления элементов запроса не существует. Порядок не определён. Есть только один констрейнт -- условия в HAVING при наличии GROUP BY вычисляются после выполнения группировки (или по крайней мере в процессе её выполнения). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 13:19 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
MasterZiv... порядка вычисления элементов запроса не существует. ... Странно. "Жопа есть, а слова нет". Вычисления есть, а их порядка нет... Значит Вы тоже не знаете. Жаль. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 13:28 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalichВсе здОрово: параметры выставил, на запрос с "explain analyze" полюбовался, порадовался скорости выполнения. Но возник еще один, возможно глупый вопрос: "explain analyze" снимаю, чтобы работать с реальными данными, и вижу, что настройки: "set enable_material to 0;" и "set work_mem to '16Mb' " без "explain analyze" уже не действуют. Для запроса: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Суммарное время выполнения запроса: 5032 ms (он же с "explain analyze": 694.387 ms). Для запроса: Код: plsql 1. 2. 3. 4. 5. 6. 7. Суммарное время выполнения запроса: 4968 ms (он же с "explain analyze": 1642.155 ms). P.S. других настроек не трогал, данные в таблице не менял. без explain analyze время выполнения запроса включает в себя a)передачу ответа по сети б)прием ответа клиентов попробуйте с локального (для базы) хоста выполнить запрос... и посмотреть на время... 50000 строк передать по сети вообще долгий процесс ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.01.2013, 14:40 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Maxim Boguk, все дело в том, что именно на localhost-е все это и наблюдается. Т.е. передачи по сети не было. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2013, 13:54 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
Viacheslav_mihalichMaxim Boguk, все дело в том, что именно на localhost-е все это и наблюдается. Т.е. передачи по сети не было. а сделайте Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. и Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. и пришлите какие времена у вас получились (при work_mem 16Mb и set enable_material to 0;) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2013, 14:09 |
|
||
|
оптимизация запроса
|
|||
|---|---|---|---|
|
#18+
При work_mem 16Mb и set enable_material to 0; 1. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Суммарное время выполнения запроса: 375 ms. 1 строка получена. count: 50011, 2. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. Суммарное время выполнения запроса: 78 ms. 1 строка получена. count: 50011. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.01.2013, 15:16 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=38127315&tid=1997574]: |
0ms |
get settings: |
6ms |
get forum list: |
13ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
154ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
56ms |
get tp. blocked users: |
1ms |
| others: | 221ms |
| total: | 465ms |

| 0 / 0 |
