|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Коллеги, что-то вдруг уперлись в странную проблему (сервер postgresql 12) Есть такой запрос: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
У него такой план: Код: 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.
И в этом плане всё нас устраивает. К нему шли долго, включая обсуждения на sql.ru Но, этот запрос исполняется на самом деле в такой вот обертке: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
И вот тут случается странное. Когда появляется insert into... то план меняется на такой: Код: 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.
Т.е. появился почему-то Seq Scan on interviews и как итог 21 секунда на запрос, хотя сама выборка без insert 732 ms и она выдает 0 строк, т.е. и вставлять ничего не надо. Что не так? Куда смотреть? Что крутить? Беда пришла такая вдруг, она не на всех запросах проявляется, но тут - гарантировано. Явно мешает join в таблицу, в которую будет и insert. Но почему? Помогите разобраться. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.11.2020, 22:20 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Таблица counter_interviews имеет такую структуру: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
... |
|||
:
Нравится:
Не нравится:
|
|||
27.11.2020, 22:25 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Несколько улучшается (заметно, но без понимания всё равно) ситуация, если заменить civ.id is null на civ.interview_id is null, время выполнения получается 3000 ms примерно. Такое же время выходит если вообще убрать join в counter_interviews (делается это для проверки дубликатов), заменив его на on conflict do nothing. Но... в плане запроса всё равно есть seq scan и получаем 3000 ms при вставке 0 строк из запроса, который сам по себе выполняется за 700ms. Запрос без join: Код: plsql 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
27.11.2020, 22:43 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Alexey Trizno, Все просто в select плане есть слово -> Parallel в 4 worker любые пишущие запросы не параллеляться (архитектурное ограничение) поэтому выполняется в 1 поток и в 4 раза дольше. Есть подкрутить настойки базы можно в 8 потоков select делать и еще в 2 раза быстрее но insert от этого не ускорится. Учитывая https://www.postgresql.org/docs/12/when-can-parallel-query-be-used.html документацияEven when it is in general possible for parallel query plans to be generated, the planner will not generate them for a given query if any of the following are true: The query writes any data or locks any database rows. If a query contains a data-modifying operation either at the top level or within a CTE, no parallel plans for that query will be generated. As an exception, the commands CREATE TABLE ... AS, SELECT INTO, and CREATE MATERIALIZED VIEW which create a new table and populate it can use a parallel plan. Можно получить нужную вам скорость через begin; create temp table t1 on commit drop as ваш select; insert into counter_interviews select * from t1; commit; но это хорошо работает пока не слишком часто вызывается (ну там не чаще 10 раз в секунду лучше меньше). -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
27.11.2020, 22:53 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Maxim Boguk, Спасибо. Пока не понятно только - почему в select-плане есть только index scan и index only scan, а в insert-select плане появляется seq scan на 8 млн строк? Ну и разница выходила (пока был left join + civ.id is null) 732 ms против 21481 ms, т.е. совсем не в 4 раза, а почти в 30. Вариант с temp не подойдет, эти запросы могут идти пачками по несколько тыс. штук. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.11.2020, 12:47 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Alexey Trizno, пачка по несколько тысяч штук раз в сутки проблем не создаст... а вот 100 раз в секунду постоянно - проблема будет для временных таблиц. теперь к плану и запросу. покажите что у вас показывает show random_page_cost; show seq_page_cost; show effective_cache_size; и set max_parallel_workers_per_gather to 0; explain (analyze, costs, buffers, timing) ваш SELECT (не insert); и второй вариант set max_parallel_workers_per_gather to 0; set enable_seqscan to 0; explain (analyze, costs, buffers, timing) ваш SELECT (не insert); -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
28.11.2020, 18:32 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Maxim Boguk, Примерно так: random_page_cost = 1.1 (база на ssd дисках) seq_page_cost = 1 effective_cache_size = 45GB Запрос после set max_parallel_workers_per_gather to 0 Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
Результат: Код: 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.
И тот же запрос после дополнительного set enable_seqscan to 0 Код: 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
30.11.2020, 11:40 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Alexey Trizno Код: sql 1. 2. 3. 4. 5. 6. 7.
Поэкспериментируйте с расширенной статистикой для таблицы answers со столбцами interview_id, question_number, answer_code, open_value_num. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.11.2020, 16:48 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Alexey Trizno, Ага тогда давайте упрощать задачу далее... Что показывает Код: plsql 1. 2. 3. 4.
и тот же explain analyze после установки set max_parallel_workers_per_gather to 0; Если там будет разница и по плану и по скорости сильная мы дойдем до разумного минимального плана где легко можно попробовать понять что не так с планированием. Мое мнение (ГИПОТЕЗА) что нормализации плана поможет или установка random_page_cost=0.11 seq_page_cost=0.1(т.е. уменьшить в 10 раз) или установка cpu_tuple_cost=0.1 (увеличить в 10 раз). -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
30.11.2020, 23:16 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Maxim Boguk, Первый запрос вот так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
После set max_parallel_workers_per_gather to 0; так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Разница по скорости в 6 раз получилась. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.11.2020, 23:23 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Alexey Trizno, Угу вот и получили минимальный проблемный запрос собственно (и ни exists ни insert ни " расширенной статистикой для таблицы answers" тут не причем). Оценки количества строк - в порядке оценки селективности join - в порядке.... а план - кривой. А какой план будет если сделать set max_parallel_workers_per_gather to 0; set seq_page_cost to 0.1; set random_page_cost to 0.11; и повторить explain analyze что делали. у меня все таки теория что *_cost расставлены в базе не в соответствии с реальностью. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
30.11.2020, 23:44 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Maxim Boguk, После этих трех set-ов запрос: Код: plsql 1. 2. 3. 4.
Работает так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
А исходный запрос: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Так (после 2-3 выполнений): Код: 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.
Он же при set max_parallel_workers_per_gather to 4; так: Код: 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
01.12.2020, 09:30 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Alexey Trizno, Ну вот теперь похоже на правду и то что я хотел добиться от базы. Я бы новые seq_page_cost / random_page_cost внес в глобальный конфиг базы как более отражающие реальность в ваше случае. Я уже давно заметил что 1:100 seq_page_cost / cpu_tuple_cost реальность не отражает для баз на ssd (и тем более для баз в основном в памяти) и 1:10 дает более разумные планы в среднем. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
01.12.2020, 09:57 |
|
Почему появляется Seq Scan при insert into T from select, если в выборке есть join в T ?
|
|||
---|---|---|---|
#18+
Maxim Boguk, Спасибо! Попробуем, последим. Как раз для баз используем nvme-диски под основные данные (постоянного обращения) и ssd для хранения собираемых данных. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.12.2020, 10:00 |
|
|
start [/forum/topic.php?fid=53&fpage=19&tid=1994352]: |
0ms |
get settings: |
9ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
42ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
49ms |
get tp. blocked users: |
2ms |
others: | 290ms |
total: | 426ms |
0 / 0 |