ADG Оставить заявку
Блог Данные и аналитика 4 мин чтения

PostgreSQL 17 Beta 1: переработанный VACUUM - гоняем на тестовом стенде рядом с PG 16

PostgreSQL 17 Beta 1 вышел с переработанным VACUUM, улучшенным планировщиком и JSON SQL/2023. Разворачиваем тестовую среду и сравниваем поведение на OLTP-нагрузке.

Контекст момента

PostgreSQL 17 Beta 1 вышел с переработанным VACUUM, улучшенным query planner и новыми функциями JSON SQL/2023

PostgreSQL выпустил Beta 1 семнадцатой версии - и в этот раз анонс зацепил нас сильнее, чем обычно. Не потому что JSON SQL/2023 или query planner (хотя и это интересно), а потому что в changelog первым пунктом идёт переработанный VACUUM. Для DWH и высоконагруженных OLTP-баз, где vacuum - это не фоновый шум, а полноценный участник производительности, это прямо по адресу.

Бета - не продакшн, но разворачивать стенд и смотреть поведение лучше сейчас, чем за неделю до GA.

Что изменили в VACUUM

Основное изменение в PG 17 - переработка внутреннего цикла autovacuum и алгоритма обработки мёртвых строк. Если коротко: в старом поведении VACUUM при обходе таблицы накапливал список мёртвых tuple-идентификаторов (TID) в памяти, и когда буфер заканчивался (maintenance_work_mem или лимит autovacuum_work_mem), приходилось прерываться, лезть в индексы, чистить их, и начинать заново. На больших таблицах это могло выродиться в несколько проходов по индексам.

В PG 17 алгоритм переработан: VACUUM теперь делает за один проход по таблице полную разметку того, что нужно убрать, и число проходов по индексам сокращается. На таблицах с агрессивной update-нагрузкой - а это типичный OLTP с частыми изменениями строк - разница в объёме I/O при вакуумировании должна быть заметной.

Второй момент - изменения в vacuumlo. Утилита для очистки осиротевших large objects стала менее навязчивой при работе в транзакции. Это нишевый кейс, но у одного из наших клиентов есть устаревший пайплайн, который активно использует lo - там посмотрим отдельно.

Стенд: PG 16 vs PG 17 Beta 1 рядом

Развернули два инстанса на одном железе: PG 16.3 и PG 17 Beta 1. Железо - обычный тестовый сервер, не продакшн. Конфигурация намеренно одинаковая: shared_buffers, work_mem, autovacuum_vacuum_cost_delay - зеркальные значения на обоих.

Для нагрузки взяли синтетику, максимально похожую на реальный OLTP: таблица с ~50 млн строк, интенсивный поток UPDATE по случайным ID, параллельно SELECT-запросы по диапазонам. Это условия, при которых мёртвые строки накапливаются быстро и VACUUM работает непрерывно.

Что наблюдали через pg_stat_io и pg_stat_user_tables:

  • Число index scan в рамках autovacuum - на PG 17 заметно меньше при той же интенсивности UPDATE. На нашем стенде примерно вдвое, но это синтетика, реальные цифры будут зависеть от соотношения maintenance_work_mem к размеру таблицы.
  • Время вакуумирования одного цикла - чуть короче, что важно не само по себе, а потому что vacuumed table остаётся под lock на этот период. Меньше циклов - меньше шанс словить конкуренцию с боевыми запросами.
  • n_dead_tup в динамике - на обоих инстансах autovacuum справляется, принципиальной разницы в steady-state нет. Но в моменты всплеска UPDATE - когда мёртвые строки накапливаются быстрее, чем autovacuum успевает - PG 17 восстанавливается чуть быстрее.

Важная оговорка: это бета, и гонять такие сравнения надо понимая, что поведение может измениться до GA.

Query planner: что интересного

В PG 17 улучшена оценка строк для некоторых паттернов с подзапросами и CTE. На нашем стенде запустили несколько тяжёлых аналитических запросов с WITH - в паре случаев планировщик выбрал более удачный join-порядок без дополнительных хинтов. Проверяли через EXPLAIN ANALYZE, разница видна в estimated vs actual rows.

Это не революция, но планировщик PG - это система, которую улучшают итерационно, и каждое улучшение оценки рядов сокращает количество случаев, когда нужно вручную помогать через enable_* параметры или материализацию CTE.

JSON SQL/2023: смотрим, но не торопимся

PG 17 дополняет поддержку стандарта JSON SQL/2023 - в частности, функции JSON_TABLE, JSON_EXISTS, JSON_QUERY и JSON_VALUE теперь работают в рамках SQL-стандарта. Это хорошо с точки зрения переносимости - одинаковый синтаксис с другими СУБД.

На практике у большинства наших клиентов JSON в PostgreSQL хранится или в jsonb с операторами ->>, @>, или через специализированные колонки. Переход на ISO-функции - скорее вопрос новых проектов, чем миграции существующего кода. Пощупали на стенде - работает, синтаксис непривычный после операторного подхода, но для кросс-СУБД совместимости аргумент есть.

Что дальше

Beta 1 - это начало цикла. До GA обычно несколько бета-итераций и RC, исторически это занимает несколько месяцев. В продакшн PG 17 раньше конца года не пойдёт - и не должен.

Наш план: держать тестовый стенд актуальным по мере выхода следующих бет, особенно в части VACUUM - это то, что реально влияет на поведение под нагрузкой. Если поведение с maint_work_mem и агрессивным UPDATE подтвердится на Beta 2-3, к моменту GA у нас будет чёткое понимание, что изменить в autovacuum-конфигурации при миграции.

Пока - PG 16 в продакшне, PG 17 на стенде. Так и должно быть с бетой.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.