|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
Есть запрос который по неясной причине ведет себя по разному на 9.4 и 10 версии базы Все примеры ниже приведены со специально установленных серверов с одинаковым набором данных (залит один дамп, 1000000 строк) Структура базы, индексы и последовательности тоже абсолютно одинаковые Результаты запуска EXPLAIN ANALYZE соответствуют тому что выдает EXPLAIN и я их не привожу. На 10-й видно что индексы НЕ используются - Seq Scan Код: 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.
На 9-й (запрос тот же просто не отформатирован) Видно использование индексов Index Scan Код: sql 1. 2. 3. 4. 5. 6.
Т.е. поведение (и естественно время работы) различное Есть предположение что планировщик "сильно хитрый" и эврестически определяет "раз там лимит всего 1 то начнем с начала сканить авось быстро найдем нужную запись" Это предположение подтверждается тем что если переделать запрос то индексы начинают использоваться Код: 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.
Аналогично, если в запрос добавить ORDER BY RANDOM() то индексы начинают использоваться. - Это поведение настраивается ? Где-то задокументировано? В ченжлоге ничего похожего нет - И вообще это баг или фича? - Есть ли идеи как можно изменить поведение кроме как SET enable_seqscan = OFF; ... |
|||
:
Нравится:
Не нравится:
|
|||
14.07.2018, 20:13 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
egusakova, Как ни странно именно v10 исходя из статистики ведет себя корректно. :) Покажите итоги на v10 следующих запросов explain analyze select * from articles where type='Tweet'; explain analyze select * from articles where masked_url_md5 IS NULL; explain analyze select * from articles where masked_url_md5 IS NULL AND type='Tweet'; у вас походу корреляция между этими двумя условиями. Что можно посоветовать или v1: индекс на articles(type) where masked_url_md5 IS NULL с последующим analyze articles или если v1 не помогает то использовать фичу 10 с create statistics: CREATE STATISTICS ON type, masked_url_md5 FROM articles ; с последующим analyze articles И проверкой вашего запроса. Проблема в следующем на самом деле: -> Bitmap Index Scan on new_articles_proc_phase_type_duplicates_mapped_duplicate_ma_idx (cost=0.00..4833.77 rows=45129 width=0) (actual time=123.466..123.466 rows=0 loops=1) Index Cond: (((type)::text = 'Tweet'::text) AND (masked_url_md5 IS NULL)) И исходя из статистики 10 поступает более верно... быстрее найти seq scanом 1 строку из 50k в таблице на 1M (это всего 20 строк проверить в среднем) чем лезть в индекс. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
14.07.2018, 21:23 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
@Maxim Boguk Спасибо за ответ! Как ни странно именно v10 исходя из статистики ведет себя корректно. :) Не могу согласится - на реальных данных (а не жалком 1М строк) запрос на 10-м отрабатывает ~800 секунд а на 9-м меньше 1 секунды (но результаты explain не отличаются - индекс не используется на 10-ке) Уточню, что я создала лабу из 2-х линуксов с 9-м и 10-м постгресом и залила туда 1М записей из оригинальной таблицы что б сравнить поведение. На самом деле таблица значительно больше (67 гиг данных) Собственно сама задача поиска проблемы возникла из-за замедления приложения после перехода на 10-ку Покажите итоги на v10 следующих запросов На 9 и на 10 вывод одинаковый Код: 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.
v1: индекс на articles(type) where masked_url_md5 IS NULL с последующим analyze articles Код: sql 1. 2.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Т.е насколько можно судить индекс все так же не используется. или если v1 не помогает то использовать фичу 10 с create statistics: CREATE STATISTICS ON type, masked_url_md5 FROM articles ; с последующим analyze articles И проверкой вашего запроса. Код: sql 1. 2. 3. 4.
Тут видно что запрос действительно медленный : Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Для сравнения с 9-ки Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
Проблема в следующем на самом деле: -> Bitmap Index Scan on new_articles_proc_phase_type_duplicates_mapped_duplicate_ma_idx (cost=0.00..4833.77 rows=45129 width=0) (actual time=123.466..123.466 rows=0 loops=1) Index Cond: (((type)::text = 'Tweet'::text) AND (masked_url_md5 IS NULL)) И исходя из статистики 10 поступает более верно... быстрее найти seq scanом 1 строку из 50k в таблице на 1M (это всего 20 строк проверить в среднем) чем лезть в индекс. Это пояснение мне к сожалению не ясно. Дядя, я не настоящий сварщик (с) (я DBA поневоле - надо решить задачу переезда и опыт с постгресом очень небольшой) >быстрее найти seq scanом 1 Это полный перебор, разве нет? Т.е возможно я не верно интерпретирую то что показывает EXPLAIN Я читала вывод так "планировщик считает что для 1М записей он найдет то 1 что требуется по лимиту и соответствует условию просто перебором в лоб (так как ему нужна всего одна запись)" Но так как по факту в таблице таких записей нет - то запрос фактически исполняется медленно и эквивалентен "SELECT "articles".* FROM "articles";" Можете пожалуйста пояснить подробнее (или дать ссылку на правильное место в документации) ... |
|||
:
Нравится:
Не нравится:
|
|||
14.07.2018, 23:08 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
egusakova, Ваша проблема "Но так как по факту в таблице таких записей нет - то запрос фактически исполняется медленно и эквивалентен "SELECT "articles".* FROM "articles";"" при том что планировщик считает что их в вашей тестовой таблице rows=44131 штук отсюда все проблемы. Надо разбираться где у вас статистика кривая (по какому набору условий в вашем запросе). Впрочем для начала объясните наличие в запросе одновременно "articles"."masked_url_md5" IS NOT NULL и "articles"."masked_url_md5" IS NULL Чтобы это значило кроме попытки специально сломать планировщику мозг :) ? -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
15.07.2018, 01:07 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
egusakova, Кстати ну очень интересно что на десятке показывает explain analyze select * from articles where ("articles"."masked_url_md5" IS NOT NULL) and ("articles"."masked_url_md5" IS NULL); -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
15.07.2018, 01:23 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
Впрочем для начала объясните наличие в запросе одновременно "articles"."masked_url_md5" IS NOT NULL и "articles"."masked_url_md5" IS NULL Это очень хороший вопрос. Запрос выдернут из логов приложения и я перепроверила - NULL/NOT NULL там не параметризируются. Похоже на ошибку/опечатку. Чтобы это значило кроме попытки специально сломать планировщику мозг :) ? Да, похоже, но почему 10-й сходит с ума а 9-й нет? Не ясно :( Кстати ну очень интересно что на десятке показывает explain analyze select * from articles where ("articles"."masked_url_md5" IS NOT NULL) and ("articles"."masked_url_md5" IS NULL); 10-ка (c дополнительным индексом и CREATE STATISTICS eg_1 ON type, masked_url_md5 FROM articles; что, похоже, влияет на скорость работы) Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
9-ка Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9.
Разница в 4 раза Это не "боевая" база - не ясно как могла "сломаться" статистика - тут за все время жизни была только одна операция записи - загрузка данных из файла Остальные запросы - SELECT ... |
|||
:
Нравится:
Не нравится:
|
|||
15.07.2018, 15:25 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
egusakova, 1)При смене major версии базы конкретный запрос может стать как быстрее так и медленнее. 2)Чем более кривой запрос - тем больше шансы на то что план поедет в сторону замедления при смене major версии базы. 3)В данном конкретном случае - наиболее правильно исправить заведомо неверный запрос. 4)Еще может быть разница в настройках 9.4 и 10.0 инсталляций которая влияет на выбор плана. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
15.07.2018, 18:53 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
Maxim Bogukegusakova, Как ни странно именно v10 исходя из статистики ведет себя корректно. :) хмм очень странное утверждение. он должен вертать пустое мн-во мгновенно , не лазая в статистику. найдя 2 взаимоисключающих ещё во время разбора итого -- ещё одно подтверждение невероятного колхоза в планировщике пж. что в 9 что в 10 и чем дальше в лес, тем партизанен наваристей ... |
|||
:
Нравится:
Не нравится:
|
|||
16.07.2018, 10:12 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
qwwqMaxim Bogukegusakova, Как ни странно именно v10 исходя из статистики ведет себя корректно. :) хмм очень странное утверждение. он должен вертать пустое мн-во мгновенно , не лазая в статистику. найдя 2 взаимоисключающих ещё во время разбора Я написал исходя из СТАТИСТИКИ а не из здравого смысла. Никто не заморочился проверкой на то что в запросе может быть 2 взаимоисключающих IS NULL/IS NOT NULL потому что такое в нормальном случае не возникает а на все возможные странные вещи эвристики писать - индусов не напасешься. Я даже баг репорт писать не стал чтобы не выглядеть идиотом. :) -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
16.07.2018, 11:35 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
Maxim BogukЯ даже баг репорт писать не стал чтобы не выглядеть идиотом. :) -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru писать идиотам что они идиоты -- действительно дело сомнительной полезности. улыбаемся и машем Код: 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.
д,б. (лавров) ... |
|||
:
Нравится:
Не нравится:
|
|||
16.07.2018, 13:23 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
qwwqписать идиотам что они идиоты -- действительно дело сомнительной полезности. Действительно. Поэтому это сообщение --- не тебе, а другим читающим тему. qwwqулыбаемся и машем Если действительно интересно, используем: Код: sql 1.
Повторяем приведённые тесты, улыбаемся веселее. Дело в том, что целью планировщиков (во всех СУБД!) не является построение наилучших планов запросов. Их цель --- построение приемлемых планов за приемлемое время, вот и всё. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2018, 00:55 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
PgSQLanonymous3, Интересный эффект с constraint_exclusion. И опять вы показали какие то незнакомые для меня стороны базы. Hmm... PS: автору топика - включите в конфиге constraint_exclusion=on на 10той версии и проблема уйдет. Это не значит что такие запросы надо использовать впрочем. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2018, 01:23 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
egusakovaЕсть запрос который по неясной причине ведет себя по разному на 9.4 и 10 версии базы На 10-й видно что индексы НЕ используются - Seq Scan На 9-й (запрос тот же просто не отформатирован) Видно использование индексов Index Scan - Это поведение настраивается ? Где-то задокументировано? В ченжлоге ничего похожего нет Ой-вей, ну что Вы таки говорите, что нигде нет. Они же предупреждали, что в 10-ке будут активно развивать параллелизм. Помнится, что полгода назад Кори Такер пытал разработчиков, почему у него на 9.6 и 10.3 разные планы выполнения. Сначала Дэвид Роули из 2ndquadrant, потом Том Лейн подключился. Выясняли, что планировщик таки думает, что parallel seqscan в 10-ке будет быстрее, чем nonparallel indexscan. А самое забавно, что было удаление из таблицы с использованием WHERE NOT EXISTS и условий через OR, а внутри был select 1 .... При этом удаление никак не параллельная операция. То есть планировщик смотрит исключительно на условие типа select 1 или limit 1 - и в 10-ке начинает думать, что все легко и просто . То есть придется его учить через явный вывод limit 1 из куска, который поступает на анализатор, вот это "SELECT * FROM T LIMIT 1" - очень правильный путь. Не нужно бороться с планировщиком, нужно подсказать анализатору. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2018, 03:55 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
PgSQLanonymous3Если действительно интересно, используем: Код: sql 1.
Повторяем приведённые тесты, улыбаемся веселее. ога, даже от безнадёжных манагерков случаются пользы. начётчики вещь в хозяйстве невредная, если к месту приставить. премного блаадаренЪ Код: 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.
ПС: всё ещё ждём-с выкладок по некошерному рекавери. ну или каких иных пояснений ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2018, 10:52 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
зы было Код: sql 1. 2. 3.
... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2018, 10:54 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
PgSQLanonymous3Если действительно интересно, используем: Код: sql 1.
Повторяем приведённые тесты, улыбаемся веселее. В настоящее время исключение по ограничению разрешено по умолчанию только в условиях, возникающих при реализации секционированных таблиц. Включение этой возможности для всех таблиц влечёт дополнительные издержки на планирование, довольно заметные для простых запросов, но никакого выигрыша это не приносит. Если вы не применяете секционированные таблицы, лучше всего полностью отключить эту возможность. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2018, 11:29 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
egusakova@Maxim Boguk Спасибо за ответ! Как ни странно именно v10 исходя из статистики ведет себя корректно. :) Не могу согласится - на реальных данных (а не жалком 1М строк) запрос на 10-м отрабатывает ~800 секунд а на 9-м меньше 1 секунды (но результаты explain не отличаются - индекс не используется на 10-ке) Уточню, что я создала лабу из 2-х линуксов с 9-м и 10-м постгресом и залила туда 1М записей из оригинальной таблицы что б сравнить поведение. На самом деле таблица значительно больше (67 гиг данных) Можете пожалуйста пояснить подробнее (или дать ссылку на правильное место в документации) 9.4 и установка work_mem - у Вас получается lossy/exact pages for bitmap heap scan. Серверы под версиями 9.4 и 10 настроены абсолютно одинаково по всем переменным? ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2018, 12:35 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
xojenisojЕсли вы не применяете секционированные таблицы, лучше всего полностью отключить эту возможность. А если таблицы секционированные - лучше срочно накатить 10.4, хотя бы по причине "Correctly enforce any CHECK constraints on individual partitions during COPY to a partitioned table". ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2018, 12:36 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
xojenisojВ настоящее время исключение по ограничению разрешено по умолчанию только в условиях, возникающих при реализации секционированных таблиц. Включение этой возможности для всех таблиц влечёт дополнительные издержки на планирование, довольно заметные для простых запросов, но никакого выигрыша это не приносит. Если вы не применяете секционированные таблицы, лучше всего полностью отключить эту возможность. Так это именно та мысль, которую я хотел донести (просто другими словами). В PostgreSQL это, кстати, особенно выражено. IMHO, как минимум, по двум простым причинам: 1. Архитектура планировщика (а она "классическая", такая ещё в System R была, кажется) не очень-то удобна для контроля времени планирования, а, наоборот, располагает к "as fast as possible". 2. "Личная" причина: представьте, сидит кто-нибудь из committer-ов и думает: "На какой бы из (допустим) 20 возможных проектов улучшения планировщика мне потратить время моей единственной жизни ? Может, сделать его более терпимым к коду идиотов людей, которые пишут лишние или противоречащие друг другу условия, недетерминированные запросы, или даже просто неидиоматический SQL?" Как вы думаете, как они себе отвечают на этот вопрос? ;) У разработчиков какой-нибудь другой, коммерческой СУБД (которым платят и "заказывают музыку"), наверное, есть и другой ответ на этот вопрос... ... |
|||
:
Нравится:
Не нравится:
|
|||
17.07.2018, 23:31 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
PgSQLanonymous3, допустим генерирует автомат мильон условий. и таких автоматов много. "тысячи их" и в кажинном таком автомате прикажете свой анализатор условий -- предпланировщик рисовать ? ась ? то то и оно то а анализ на ексклюжны , если безпартиционные, можно и отпараллелить. чтобы снимал запрос как до противоречия доберется. или усекал дерево планирования и перезапускал запрос-- если партиечки или части юниона сумел усечь. а не прятаться за ну вы с вашим зеркалом с двух рук по македонски можете дальше побеседовать, потешить т.с. публику ... |
|||
:
Нравится:
Не нравится:
|
|||
18.07.2018, 09:27 |
|
Разное поведение запроса с LIMIT 1 на 9.4 и 10
|
|||
---|---|---|---|
#18+
Коллеги, огромное спасибо за ответы - моя проблема так или иначе решена. Проблема в коде который действительно генерировал неверный запрос - исправили со стороны кода а не со стороны базы (хотя это и не то чего мне хотелось бы) @Maxim Boguk: СПАСИБО! Внимательность - Ваше "второе Я" Все действительно настолько очевидно, но только если знать в чем дело. @Andy_OLAP 9.4 и установка work_mem - у Вас получается lossy/exact pages for bitmap heap scan. Серверы под версиями 9.4 и 10 настроены абсолютно одинаково по всем переменным? Конечно, сервера для тестов ставила "с нуля" с дефолтными настройками, а потом проверяла значения всех переменных (и сравнивая с продакшен/стейджинг установками) Все одинаково с точностью до путей/имен файлов Я не смогла найти никаких настроек которые бы _явно_ отличались Аналогично сравнила конфиги - значимой разницы не нашла Возможно есть какие-то "скрытые" умолчания но опять же нагуглить что-либо не вышло. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.07.2018, 00:01 |
|
|
start [/forum/topic.php?fid=53&msg=39674086&tid=1995668]: |
0ms |
get settings: |
8ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
35ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
58ms |
get tp. blocked users: |
1ms |
others: | 292ms |
total: | 422ms |
0 / 0 |