|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Добрый день! Что-то при переводе базы с mssql на postgresql упёрся в странную проблему, которой не было на mssql вовсе. Есть запрос вида (генерируется автоматически по свободным выражениям, которые пишет пользователь): Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
Структура подчинения таблиц проста: respondents -> interviews -> answers. mssql на таком запросе всё как-то сам прекрасно оптимизировал, что не приводило к скану таблицы answers - из неё рассматривались только нужные строки. Тут важный момент - в answers хранится бесконечное кол-во записей, и скан по ней это вообще не вариант. Также как по respondents или interviews. Если убрать первый exists с проверкой (answer_code >= 2 and answer_code <= 7) - всё становится чуть лучше, но не кординально, да и нельзя убрать такое - пользователь может написать любое условие, куда более сложное. Главное непонимание - почему сервер начинает сканировать все записи answers? Чего в принципе никогда делать не будет mssql. Нынешний план запроса: Код: plaintext 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.
Что ещё больше меня смутило (вероятно я совсем не понял, как работает оптимизатор в pg), что такой запрос: Код: sql 1. 2. 3. 4. 5. 6. 7.
тоже приводит чуть ли не к сканам, хотя конечно есть индекс по respondents.project_id и вроде бы свести джоин сервер должен без прохода по всей interviews. План: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
Направьте пожалуйста, куда копать? Чувствую что ошибка в подходе, т.к. имеется большое наследие по работе с mssql, который очень терпим к решению задачи в лоб. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2017, 17:57 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
"Чего в принципе никогда делать не будет mssql." даладно и не такое бывает. Структура таблиц и индексов? ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2017, 18:22 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, Давайте с второго запроса начнем. Он проще. Индекс по iv.respondent_id есть? Какой размер базы и какой размер effective_cache_size в конфиге базы? И главное какие стоят random_page_cost и seq_page_cost? Если у вас там где вы ожидаете получается seq scan вместо index scan - наиболее вероятны 2 случая 1)нет индекса или 2)неверно настроена база в районе тех параметров что я указал. PS: далеко не факт что в случае 2го запроса если nested loop будет попадать на таблицу interviews которая холодная и лежит на медленных механических дисках что index scan будет быстрее чем seq scan. По первому запросу я бы добавил индекс на answers(question_number, answer_code) и возможно (смотря на результаты) еще индекс на answers(interview_id, question_number, answer_code) если их нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
14.08.2017, 18:50 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Ниже структура таблиц. Поля не имеющие отношения к вопросу не убирал, а то вдруг...: Код: plaintext 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.
Код: plaintext 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.
Код: plaintext 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 12:06 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, размер базы сейчас 50Gb, но это она ещё "молодая" :) effective_cache_size = 16Gb а эти дефолтные: #random_page_cost = 4.0 #seq_page_cost = 1.0 На сервере базы 32Gb памяти. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 12:15 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Кол-во строк в таблицах на данный момент: answers: 37 687 200 interviews: 5 799 250 respondents: 4 578 730 ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 12:18 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno Код: sql 1. 2. 3. 4. 5.
перепиши четыре из existsов в один. Можно и одним обращением к answers обойтись, но вряд ли это улучшит ситуацию. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 13:02 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey TriznoMaxim Boguk, размер базы сейчас 50Gb, но это она ещё "молодая" :) effective_cache_size = 16Gb а эти дефолтные: #random_page_cost = 4.0 #seq_page_cost = 1.0 На сервере базы 32Gb памяти. покажите планы (оба--два) после SET LOCAL random_page_cost TO 2.0; интересно, а ежели писать Код: sql 1. 2. 3. 4.
-- ? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 13:30 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey TriznoMaxim Boguk, размер базы сейчас 50Gb, но это она ещё "молодая" :) effective_cache_size = 16Gb а эти дефолтные: #random_page_cost = 4.0 #seq_page_cost = 1.0 На сервере базы 32Gb памяти. А shared_buffers сколько? Вообще поставить random_page_cost=1.1 и сделать analyze всей базы (на всякий случай) а потом проверить оба запроса ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 15:46 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, покажите вывод (в psql) Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
диски ssd на сервере? если да - то стоит попробовать уменьшить random_page_cost как выше писали. возможно для исходного запроса я бы добавил индекс в answers по (question_number, answer_code), с которым запрос с указанными параметрами будет быстро работать. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 15:49 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, shared_buffers = 8192Mb qwwq, вот запросы и планы: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
Код: plaintext 1. 2. 3. 4. 5.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Код: plaintext 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 16:37 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
p2., переписывание exist'ов или какая-то их оптимизация в этом конкретном случае - особо не поможет, т.к. как я написал - этот запрос генерируется по произвольному выражению и юзер может написать что угодно, используя AND/OR/NOT, скобки и любые логические операции. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 16:39 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexius, диски на сервере не ssd, но там совсем не видно никакой активной работы с дисками. Тишина. Да и не такая большая база, вообще всё в кэши могло бы влезть. Вывод запросов ниже: Код: plaintext 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 16:49 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, можно еще результат запроса Код: sql 1.
? ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 17:08 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexius, результат = 3758019 ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 17:22 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, ок, рекомендации такие: 1) добавить индекс в answers по (question_number, answer_code) - должно решить проблему с 1м запросом 2) сделать Код: sql 1. 2.
так мы исправим косяк в оценке числа строк после hashaggregate, возможно появятся более интересные варианты планов и какие-то другие запросы могут получше работать дальше еще раз посмотреть план исходного запроса Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
3) уменьшить random_page_cost в конфиге с 4 до 1.1 (после изменения стоит понаблюдать за нагрузкой, т.к. какие-то запросы могут в теории хуже выполняться. но скорей всего все нужное в памяти будет). - должно решить проблему со 2м запросом 4) можно еще добавить индекс по (respondent_id, id) в interviews, если в запросах действительно только id выбирается, чтобы использовался index only scan ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 17:48 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexius, спасибо, попробую. Результаты напишу. ... |
|||
:
Нравится:
Не нравится:
|
|||
15.08.2017, 17:54 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexius, всё сделал, стало значительно лучше, на мой взгляд: Код: plaintext 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
16.08.2017, 14:55 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, Думаю что принципиально быстрее чем сейчас это можно будет сделать быстрее только когда 10.0 выйдет (да и то сильно не факт). Вполне нормальная сейчас производительность получилась. -- Maxim Boguk dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
16.08.2017, 17:15 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, да, сейчас вполне. Скорее всего надо ещё как-то правильно отконфигурить параметры сервера, на тему использования памяти и прочего. Ещё есть момент, что в answers для расчетов выражений (по которым строится sql-запрос) есть не только answer_code поле, но и ещё как минимум одно row_code, и ещё пара полей. Чтобы всё это красиво считалось - получается надо море вариантов индексов... Например если юзер проверяет только answer_code - то нужен индекс по question_number + answer_code. А если проверяет row_code, то надо question_number + row_code, но часто бывает что проверяется одновременно answer_code и row_code, и тут не понятно что надо уже... индекс по question_number + answer_code + row_code? И надо ли туда добавлять interview_id? По ощущению он только портит всё, хотя странно почему... с ним не работает проверка answer_code не на равенство, а на >= и т.д. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.08.2017, 17:25 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Может что-то ещё можно покрутить в настройках? Жутко не стабильные результаты выполнения запросов получаются. Один и тот же запрос может выполняться то более 30 сек., то < 1 сек. Длительное выполнение обычно если какое-то время не трогали эти запросы. Вот пример: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Заняло 20 сек. аж, хотя предыдущий запрос свалился по таймауту (30 сек.) Ещё раз выполняем: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
Вот текущий план из этого селекта: Код: plaintext 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 18:40 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, Когда сильно скорость плавает для одного и того же запроса это признак того что данные не в памяти а читаются с дисков что в 10000 и более раз медленнее. При этом какая часть данных в памяти сейчас а какая на дисках - никто не знает. Попробуйте включть track_io_timing в конфигe базы и делать explain (analyze, costs, buffers, timing) вместо explain analyze. Еще полезно отрестартовать попробовать базу и сразу после рестарта сделать explain (analyze, costs, buffers, timing) для проблемного запроса причем повторить его раза 3 чтобы видеть эффекты от данных в памяти или на дисках. Ну и конечно мониторинг дисковой нагрузки. -- Maxim Boguk dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 18:58 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Также решил сравнить выполнение такого же запроса на старой базе (ms sql 2012, база более 160Gb, машина в два раза слабее чем та, на которой работает pgsql, при этом эта же машина ещё и веб-сервер). В итоге запрос отрабатывает максимум за 140ms, а обычно за <100 ms. Вот запрос на mssql: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
Вот план по нему: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
И подобный же запрос на pgsql (подобрал чтобы похожее было кол-во итоговых строк в выборке): Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
И план по нему: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
Разница примерно в 10 раз по скорости, причём железо реально заметно получше. Причём, постоянное выполнение одного и того же запроса уменьшает время выполнения до 660ms минимум, меньше совсем никак. Беда какая-то совсем. Этот запрос простейший, обычно там exist-ов по 5-10 штук, с различными условиями. Как быть? Что крутить? Спасите помогите (с) Как я понимаю, mssql никогда не будет в этом случае рассматривать всю таблицу answers, а будет брать только то, что касается interviews внутри искомого project_id (из respondents). А в pgsql почему-то получается что сначала выбираем всё подходящее из answers (она может быть бесконечно большой), а потом отбираем от этого огромного кол-ва записей только подходящие по interview_id... как-то это не правильно. При таком подходе скорость выполнения запроса зависит от кол-ва записей в answers (и других таблицах), а не кол-ва записей для конкретного одного проекта, что рушит всю идею совсем. Возможно надо как-то иначе совсем переписать запрос, чтобы не было зависимости от всех записей answers? В mssql базе этой в answers сейчас 185954703 записей и постоянно добавляется, при этом скорость выполнения запросов никак от этого не зависит. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 19:06 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Пока мысль только одна - добавить в answers поле project_id, что избавит от джойна в respondents, и, возможно, как-то поможет. Но это же не наши методы, Карл! Это же избыточность и прочее. Тем более не всегда выборка идет просто для одного project_id, могут ещё участвовать поля из respondents для фильтрации нужных. Все эти поля в одну таблицу не перенести. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 19:09 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, 1)Давайте сравним что дает select count(*) from respondents r where project_id = 994; на postgresql и на mssql причем на postgresql приведите результат expain analyze. 2)Я вижу что mssql дает почти тот же план. И он тоже начинается с выбора из answers (а не как вы описали от выбора из respondends). Для теста сделайте в конфиге базы default_statistics_target=10000 и сделайте analyze всей базы. Может поможет. PS: частично проблема postgres в 30 кратной ошибке в оценке " -> Index Scan using ix_answers_questionnumber_answercode on answers (cost=0.56..4046.48 rows=3668 width=8) (actual time=0.025..137.810 rows=90146 loops=1)" " Index Cond: ((question_number = 999) AND (answer_code = 9))" откуда и выбирается неудачный план. Повышение default_statistics_target может этот вопрос решить (а может и нет). PPS: если надо могу подсказать как более менее наверняка пришпилить тот план что вы хотите если ничего другого не поможет. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 19:20 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, там совсем нет никакой нагрузки на диск :( вообще. Результат же всего 800 записей, там вообще перебирается их минимум для такой мощности системы. Вот пример статистики (выделен справа кусок, когда постоянно выполняю тестовый запрос, который ровно выполняется за ~800ms): ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 19:28 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, 800ms - максимальная скорость которая получается при выбранном плане. Как попробовать изменить план - я написал (поднять default_statistics_target и сделать analyze базы). Если не поможет - есть варианты как переписать запрос по другому. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 19:32 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, вот что вышло на pgsql: select count(*) from respondents r where project_id = 994; = 47693 план: Код: plaintext 1. 2. 3. 4. 5. 6.
на mssql (проект другой, т.к. база другая, но похож по сути): select count(*) from Respondents where ProjectID = 12138 = 50087 на этом проекте в mssql запрос тестовый выполняется примерно 400...500ms, что конечно близко к pgsql, хоть там и всё равно медленнее (можно предположить другую структуру записей, т.к. всё же разные проекты). но первое выполнение идёт жутко... ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 19:38 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, если сделать: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
то вроде бы ничего не меняется: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 19:40 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, вам надо сделать default_statistics_target в конфиге базы далее пречитать конфиг и сделать analyze; внутри вашей базы чтобы обновить статистику. -- Maxim Boguk dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 20:27 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey TriznoMaxim Boguk, вот что вышло на pgsql: select count(*) from respondents r where project_id = 994; = 47693 план: Код: sql 1. 2. 3. 4. 5. 6.
на mssql (проект другой, т.к. база другая, но похож по сути): select count(*) from Respondents where ProjectID = 12138 = 50087 на этом проекте в mssql запрос тестовый выполняется примерно 400...500ms, что конечно близко к pgsql, хоть там и всё равно медленнее (можно предположить другую структуру записей, т.к. всё же разные проекты). но первое выполнение идёт жутко...? Ы ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 20:46 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, сделал в конфиге и релоад. Вот план: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21.
analyze всей базы тоже уже сделан. идея с переписыванием запроса может поможет? в чем она заключается? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 20:52 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, судя по: (cost=0.56..4068.55 rows=3685 width=8) (actual time=0.065..177.529 rows=90214 loops=1) так и есть промах по оценке и реальности? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 20:54 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
qwwq, в смысле что всё в памяти и так? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 20:54 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, пока пробовал с одним этим проектом - в целом всё стало считаться более менее, разные виды запросов от 15 до 700 ms, что хорошо. Но беру другой проект (база эта же конечно), делаем расчет - и первый же более менее сложный запрос падает с таймаутом (30 сек), потом ещё раз его вручную выполняю - отрабатывает за 20 сек, потом ещё раз - отрабатывает за 600 мс. Как быть? Где же кэширование и прочие радости? Причём этот запрос был не первый в группе расчета по этому проекту, т.е. данные частично и так уже были прочитаны и где-то должны быть близко. Вот запрос такой, для примера: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
План: Код: plaintext 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 21:05 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey TriznoMaxim Boguk, судя по: (cost=0.56..4068.55 rows=3685 width=8) (actual time=0.065..177.529 rows=90214 loops=1) так и есть промах по оценке и реальности? "analyze всей базы тоже уже сделан." - уже ПОСЛЕ смены конфига? если нет то его надо повторить. Ну и для теста проверять просто explain analyze select * from answers where (question_number = 999) and (answer_code = 9) насколько база реалистично оценивает результаты Если не поможет - я напишу как попробовать переписать. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 21:06 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, сделал analyze ещё раз. И план такого запроса: Код: plaintext 1. 2. 3. 4.
Ничего не поменялось. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 21:18 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno Но беру другой проект (база эта же конечно), делаем расчет - и первый же более менее сложный запрос падает с таймаутом (30 сек), потом ещё раз его вручную выполняю - отрабатывает за 20 сек, потом ещё раз - отрабатывает за 600 мс. Как быть? Где же кэширование и прочие радости? Кеширование у Postgresql на уровне страниц с данными. Поэтому те данные к которым не обращались будут медленно и болезненно читаться с механического диска (где для быстрого плана нужен random_page_cost = 10 а не 1.1). Как быть: 1)ssd чтобы чтение холодных данных быстрее шло (на 2-3 порядка) 2)больше памяти чтобы данные в памяти в основном висели (но первый раз по холодным данным всегда будет медленно). PS: вот там где 600ms - это данные уже закешированы у базы. Не очень понятно что вас смущает. -- Maxim Boguk dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 22:29 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
На счет переписывания запроса - попробуйте вот так вот: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Покажите план может я еще пару вариантов подкину как можно лучше сделать. -- Maxim Boguk dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
17.08.2017, 22:32 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, так если для быстрого чтения с диска надо random_page_cost = 10, то зачем мы поставили его в 1.1? И тут я главное не понимаю - 600ms хорошее время, оно устраивает прекрасно. Не устраивает вдруг просадка в десятки раз, которую я не могу объяснить диском или ещё чем-то, т.к. всё железо быстрое, и даже тупо читая всё с диска не может простой запрос выполняться минуты, это не логично никак (при этом на сервере нулевая загрузка cpu и hdd). Нельзя же принять идею, что вдруг любой простой запрос может сваливаться по таймауту и ломать логику работы приложения вплоть до потери важных данных... это беда совсем. Если 600мс получаем при нормальной работе, то при холодном пуске можно допустить 1200, ну 1800 - но никак не 30000 и более. Про переписанный запрос - попробовал, по ощущениями выходит медленнее. Первый запуск 10 секунд, последующие где-то 960мс. План: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 12:10 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, точнее нет - без explain и analyze запрос выполняется за 60мс. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 12:12 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, и далее... сразу выполняем старую версию того же запроса (без WITH), и он выполнялся почти 2 минуты :-/ Ничего не понимаю. Данные только что были все прочитаны же... второе выполнение 250 мс. Но 2 минуты!!! Так же нельзя работать совсем :( Но в любом случае - 60 мс против 250мс, разница огромная. Вариант с WITH похоже более верный тут. Беру любой другой запрос и опять - первое выполнение длится минуты (5 и более)... даже не смог дождаться окончания выполнения - в ступор уходит всё. Оборвал. Со второй попытке запрос 9 секунд выполнялся. С третьей 556мс. Тот же запрос с WITH работает 192мс. Итого пока выводы: 1) такие запросы надо делать с WITH, т.к. сам планировщик до этого не может додуматься 2) совсем какая-то пока беда с предсказуемостью работы запросов, время выполнения может вдруг стать бесконечным, без причин ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 12:31 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Triznoqwwq, в смысле что всё в памяти и так? выходит он вместо IOS тупо IS сделал -- всякую запись из индекса проверил в хипе. вероятно или 1. цифры случайно совпали в копейку, т.е. и карта видимости старая и цифры в 00 притёрлись 2. постгрес лажает с планом -- проверить планом "select count(1) from respondents r where project_id" 3. я чего то вру (бывает) но если 46тыс хип-фетчей не забрали много времени -- то все же надо думать все было в памяти. выводите BUFFERS всегда -- будете понимать , почему времена скачут. я так думаю: вы нещадно апдейтитесь (мсскл это не вредно, а у пж и индексы пухнут и карта видимости портицца) и прочтите уже букварь по костам, что ли. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 13:38 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey TriznoMaxim Boguk, и далее... сразу выполняем старую версию того же запроса (без WITH), и он выполнялся почти 2 минуты :-/ Ничего не понимаю. Данные только что были все прочитаны же... второе выполнение 250 мс. Но 2 минуты!!! Так же нельзя работать совсем :( Но в любом случае - 60 мс против 250мс, разница огромная. Вариант с WITH похоже более верный тут. Беру любой другой запрос и опять - первое выполнение длится минуты (5 и более)... даже не смог дождаться окончания выполнения - в ступор уходит всё. Оборвал. Со второй попытке запрос 9 секунд выполнялся. С третьей 556мс. Тот же запрос с WITH работает 192мс. Итого пока выводы: 1) такие запросы надо делать с WITH, т.к. сам планировщик до этого не может додуматься 2) совсем какая-то пока беда с предсказуемостью работы запросов, время выполнения может вдруг стать бесконечным, без причин Как я уже говорил для анализа ситуации вам надо 1)включить track_io_timing в конфиге базы 2)делать подозрительные запросы через explain (analyze, costs, buffers, timing) тогда будет видно явно сколько времени проведено в работе с дисками а сколько считалось PS: время доступа к 1 странице с данными в памяти и на механическом диске отличается на 5 порядков. Поэтому достаточно 0.1% cache miss чтобы запрос замедлился в 100-1000 раз. Это вы и сами на explain (analyze, costs, buffers, timing) увидите. Методы борьбы - 1)основной - базу на ssd держать которые на 3 порядка быстрее чем механика (и всего на 2 порядка медленнее чем память) 2)выделять базе достаточно shared_buffers чтобы основные данные все таки лежали в кеше базы. Я почему то думаю что mssql или на ssd дисках живет или ему заметно больше памяти выделено (кстати интересный вариант проверить какая скорость работы у mssql сразу после рестарта сервера когда кеши холодные все). ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 13:58 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey TriznoЕсли 600мс получаем при нормальной работе, то при холодном пуске можно допустить 1200, ну 1800 - но никак не 30000 и более. Скорость случайного доступа к механическому диску и к памяти отличается на 5-6 порядков. Поэтому никаких 1800 vs 600 при холодном запуске вы НИКОГДА не получите. SSD на 3 порядка быстрее поэтому там это будет работать сильно лучше. Тут надо понимать что random_page_cost=10 приведет к плану который будет оптимально (относительно) выполнятся на холодном пуске но КРАЙНЕ не оптимально выполнятся в ситуации когда данные в памяти (поэтому тут всегда есть tradeoff и вам надо решать что вам важнее и какая часть данных у вас в памяти будет). -- Maxim Boguk dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 14:05 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim Boguk, сейчас уже включили тайминги и прочее, вроде логирования длительных запросов. План теперь более детальный, но я его не очень понимаю... прошу помощи, где искать узкие места. И ещё - может есть какой-то правильный генератор конфига для pgsql, который сделает его максимально правильным для конкретного железа? (объем памяти, диски, cpu и прочее), ибо параметров там море, и что именно как лучше поставить - не очевидно. Запрос (исполнялся 11 минут !!!): Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
План с деталями от него: Код: plaintext 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 15:31 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Alexey Trizno, Ну вот вы сами видите что из 11 минут работы на работу с диском ушло I/O Timings: read=664304.805... все 11 минут. При этом в Buffers: shared hit=767961 read=129668 dirtied=18 в кеш базы попало где то 80%... мимо кеша 20% и было сделано 130.000 обращений к диску, среднее время 1 обращения к диску 4ms -совершенно стандартная цифра для механического SAS/SATA диска. Т.е. ни чудес ни странностей тут нет. Тут надо или памяти сильно больше или диск сильно быстрее (SSD). Дальнейшие консультации по тонкой настройке железа и базы и рекомендации по производительности - выходят за пределы форума :). Можете например обратится по URL у меня в подписи. -- Maxim Boguk dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 15:49 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Maxim BogukAlexey Trizno, Ну вот вы сами видите что из 11 минут работы на работу с диском ушло I/O Timings: read=664304.805... все 11 минут. При этом в Buffers: shared hit=767961 read=129668 dirtied=18 в кеш базы попало где то 80%... мимо кеша 20% и было сделано 130.000 обращений к диску, среднее время 1 обращения к диску 4ms -совершенно стандартная цифра для механического SAS/SATA диска. Т.е. ни чудес ни странностей тут нет. Тут надо или памяти сильно больше или диск сильно быстрее (SSD). Дальнейшие консультации по тонкой настройке железа и базы и рекомендации по производительности - выходят за пределы форума :). Можете например обратится по URL у меня в подписи. -- Maxim Boguk dataegret.ru Код: sql 1. 2. 3. 4. 5. 6. 7. 8.
остывает индекс на больших выборках. нужно что-то типа full index scan https://postgrespro.ru/development/tasks/56601 совсем не обязательно читать рендомно, если известно, что надо прочитать много из. а пока, думается, можно проверить идею такого индекса: Код: sql 1.
на предмет лучших ожыданий по попаданию на уже прочитанное. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 17:03 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
qwwq, пока сделали замер скорости дисков, вышло не очень радужно: линейное чтение 170Mb/s, а рандомное чуть не в 200 раз медленнее. Но на машине 32Gb памяти, туда по идее должно влезть бОльшая часть основных данных, а уж рассматриваемые 4 таблицы вообще целиком вместе с индексами несколько раз. Зачем вообще на диск лезть для чтения? ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 18:25 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Потому что читается только то, что запрашивается. Даже если вы 'разогреете' данные сделав full scan на всех таблицах так что они пойдут в память, то и тогда эти данные могут со временем быть выгружены из кэша. Постгрес довольно трудно будет заставить закэшировать все таблицы и индексы до первого рабочего вызова. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 19:15 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Sergei.Agalakov, пока решили добавить в сервер ssd диск и перенести базу на него. Посмотрим что получится. Ну и все эти запросы теперь строятся с WITH для уменьшения выборки, что в 2-4 раза улучшает результат. ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 22:31 |
|
Помогите перенести запрос с mssql на postgresql
|
|||
---|---|---|---|
#18+
Sergei.AgalakovПостгрес довольно трудно будет заставить закэшировать все таблицы и индексы до первого рабочего вызова. Можно попробовать https://www.postgresql.org/docs/current/static/pgprewarm.html ... |
|||
:
Нравится:
Не нравится:
|
|||
18.08.2017, 23:20 |
|
|
start [/forum/topic.php?all=1&fid=53&tid=1996284]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
35ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
80ms |
get tp. blocked users: |
1ms |
others: | 321ms |
total: | 478ms |
0 / 0 |