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

PostgreSQL 16 GA: планируем миграцию с PG 14 и тестируем parallel VACUUM на секционированных таблицах

PostgreSQL 16 вышел GA 14 сентября. Тестируем parallel VACUUM и INSERT throughput на секционированных таблицах перед миграцией production-кластера с PG 14.

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

PostgreSQL 16 GA выпущен - улучшенная логическая репликация, параллельный VACUUM, pg_stat_io, 14 сентября 2023

PostgreSQL 16 должен выйти GA 14 сентября - это уже не предположение, а официальный release candidate с зафиксированной датой. Мы к этому моменту готовимся заранее: у нас в managed-сопровождении есть несколько кластеров на PG 14, и один из них - хороший кандидат на миграцию уже в четвёртом квартале. Пока бета превращалась в RC, мы гоняли стендовые тесты. Вот что реально нашли.

Почему именно с 14, а не с 15

PG 14 у клиента стоит крепко: установлен полтора года назад, схема устоялась, настройки выверены. PG 15 вышел в прошлом году, но тогда у нас не было достаточного аргумента для планового апгрейда - улучшения в merge и row-filtering для логической репликации были интересны, но не критичны под конкретный профиль нагрузки.

PG 16 даёт два конкретных довода:

  • Параллельный VACUUM для секционированных таблиц. У клиента основная таблица событий секционирована по месяцам. В PG 14 VACUUM идёт по секциям последовательно - при большом количестве активных секций это заметно. В PG 16 VACUUM умеет работать с несколькими секциями параллельно.
  • pg_stat_io. Мы уже видели этот инструмент в бете Postgres Pro 16 на другом стенде. Он меняет диагностику I/O принципиально - вместо косвенной корреляции pg_stat_bgwriter + iostat получаешь прямую разбивку по backend_type и context. На продакшне такого нам не хватало.

Логическая репликация тоже улучшилась, но клиент её не использует, так что это бонус, а не аргумент.

Стенд и что мы меряли

Стенд - реплика схемы клиентского кластера: PostgreSQL на выделенной машине, основная таблица events секционирована по 12 месяцам, в каждой секции от 20 до 80 млн строк, индексы на нескольких полях. Нагрузка - синтетика, но воспроизводящая реальный профиль: массовые пакетные INSERT в текущую секцию плюс периодические аналитические запросы по старым.

Сравниваем PG 14.9 и PG 16 RC1.

Parallel VACUUM

В PG 14 принудительный VACUUM на всей партиционированной таблице:

VACUUM (VERBOSE, ANALYZE) events;

Идёт последовательно секция за секцией - это видно в pg_stat_progress_vacuum, одна запись активна в каждый момент времени.

В PG 16 параллельный VACUUM распространился на секционированные таблицы: VACUUM теперь может запускать параллельных воркеров на разные секции одновременно. Управляется через max_parallel_maintenance_workers.

На нашем стенде при трёх параллельных воркерах общее время VACUUM по всей таблице сократилось примерно вдвое по сравнению с PG 14. На активных боевых секциях с интенсивной записью эффект ощутимее - там bloat накапливается быстрее и воркерам есть чем заняться параллельно.

Одна оговорка: параллелизм VACUUM создаёт дополнительную нагрузку на I/O. На нашем стенде пиковая нагрузка на диск во время VACUUM выросла пропорционально числу воркеров. Если кластер живёт на дисках без запаса по IOPS - нужно аккуратнее выбирать время и степень параллелизма, а не просто выкрутить воркеры на максимум.

INSERT throughput на секциях

Здесь ожидали меньшего, но проверили на всякий случай. PG 16 принёс ряд оптимизаций в планировщик для секционированных таблиц - уменьшение overhead на partition pruning при INSERT в большую схему.

На нашем стенде с 12 секциями разница при одиночных INSERT практически в пределах погрешности. При пакетных вставках через COPY или батчи по несколько тысяч строк - чуть заметнее, но не радикально. На схеме с сотнями секций эффект был бы, вероятно, более выраженным - у нас их 12, и PG 14 с этим справлялся без видимых проблем.

Вывод: для нашего конкретного кейса INSERT - не аргумент миграции. Parallel VACUUM - аргумент.

pg_stat_io в деле

После перехода стенда на PG 16 первым делом подключились к pg_stat_io. Уже в первые часы прогона под нагрузкой стало видно, что autovacuum генерирует непропорционально много read-операций на старых секциях - там индексы пухлые, таблица большая, и autovacuum пытается сделать с ними что-то разумное.

В PG 14 это пришлось бы вылавливать через pg_stat_bgwriter + iostat + корреляцию по времени. Здесь всё видно напрямую: кто, что, сколько, в каком контексте. Мы скорректировали autovacuum_vacuum_cost_delay на конкретных секциях - и нагрузка на диск в часы пиковых аналитических запросов стала ровнее.

Что дальше

GA 14 сентября - после этого даём релизу пару недель, смотрим на первые сообщения сообщества. Если ничего критичного не всплывает, начинаем готовить план миграции production-кластера: pg_upgrade или логическая репликация с минимальным downtime. У клиента есть требование по окну обслуживания, так что выбор метода ещё не финален.

Параметры max_parallel_maintenance_workers и профиль нагрузки на I/O во время VACUUM надо будет откалибровать уже на реальном железе - стенд есть стенд, там одна нода и нет боевого трафика. Но направление понятно: PG 16 для этого кластера имеет смысл, и тест это подтвердил.

Контакт

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

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