TGViewer
Postgres Professional Postgres Professional @postgres_pro · 3.53K subscribers
Post #1354 2.38K
Иногда один и тот же запрос внезапно раздувается по времени: с долей миллисекунды до минут и даже часов. Причина часто не в данных и не в железе.

Планировщик может недооценить кардинальность и стоимость шагов, выбрать слишком дешевый для себя план, а в реальности получить Nested Loop там, где выгоднее Hash Join, или Seq Scan вместо Index Scan.

Бывает и так, что дерево запроса устроено неудачно: нужные условия спрятаны, и часть эффективных алгоритмов просто не рассматривается.

Эти случаи закрывает расширение pgpro_planner. Оно переписывает неудобные для оптимизатора куски дерева запроса в более дружелюбный вид еще до того, как основной планировщик выберет план.

Ниже — три примера небольших оптимизаций с большим эффектом.

✔️ IN (VALUES ...) → = ANY(array)

В одном запросе из мира 1С фильтры были оформлены как IN (VALUES ...) для numeric и bytea. До обновления статистики он работал быстрее 1 мс, после — около 7,5 с.

В плане львиная доля времени ушла в Nested Loop Semi Join и материализацию маленьких таблиц из VALUES. Индекс почти не помогал, потому что сравнение было внутри join-фильтра, а не в Index Cond.

Решение: собрать константы VALUES в массив и переписать условие как = ANY(array). Тогда индекс попадает в Index Cond, из плана исчезают лишние Semi Join и временные таблицы, а время падает с секунд до долей миллисекунды.

Эту функциональность в итоге закоммитили в PostgreSQL 18.

✔️ Простейшая арифметика, которая ломает индекс

Выражения x + 0, x * 1, x / 1, x - 0 равны x, но планировщик не обязан это распознавать. Поэтому условие x + 0 > 900 может дать Seq Scan, хотя x > 900 позволяет построить Index Only Scan. Шаг упрощения делает предикат индексируемым еще до планирования.

✔️ Memoize для коррелированных подзапросов

В бенчмарке один и тот же подзапрос выполнялся 14 835 720 раз и давал Execution Time 496 690 мс. Узел Memoize кеширует результат по ключу параметра и возвращает его из кеша при повторе. Итог — 115 528 мс, то есть ускорение в четыре с лишним раза.

Подключается это все как обычное расширение оптимизатора: через LOAD pgpro_planner в сессии или через shared_preload_libraries с перезагрузкой.

Затем включают pgpro_planner.enable = true и при необходимости управляют отдельными функциями: преобразованием VALUES, упрощением тривиальных выражений и Memoize.

Подробности читайте на Хабре.
  • ❤ 8
  • 👍 8
  • 🔥 3
More from @postgres_pro
  1. Sep 28, 2026🚀 Наш метод доступа iHeap ускоряет выборку из больших таблиц PostgreSQL и сам создает инд…
  2. Sep 24, 2026🚀 Показываем, как перенести тяжелые отчеты 1С на реплику Postgres Pro Enterprise для 1С и…
  3. Sep 23, 2026⏰ Через час, в 11:00 по Москве, начнем вебинар «Postgres Pro Backup Enterprise: от бэкапа…
  4. Sep 22, 2026🌅 Утро вечера мудренее. Особенно если завтра 23 сентября и последний день приема докладов…
  5. Sep 22, 2026Tarkett перенесла 1С и 1С:ЗУП с Microsoft SQL Server на Postgres Pro Enterprise для 1С — н…
  6. Sep 21, 2026🗂️ От бумажных картотек до поиска по смыслу — как базы данных стали основой цифровых серв…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →