LIST PARTITION
Тема дорожной карты · PostgreSQL
Секционирование по списку в PostgreSQL делит таблицу на дочерние секции, каждая из которых содержит строки, у которых значение столбца ключа секции совпадает с определённым набором дискретных значений. В отличие от секционирования по диапазону, использующего непрерывные интервалы, секционирование по списку идеально подходит для категориальных данных, таких как коды стран, статусные метки или региональные идентификаторы в реляционной базе данных. При определении секции по списку синтаксис PARTITION OF ... FOR VALUES IN (...) перечисляет точные значения, принадлежащие данной дочерней таблице, а PostgreSQL автоматически направляет операторы INSERT в правильную секцию во время выполнения запроса. Планировщик SQL-запросов может отсекать неактуальные секции, когда предложение WHERE фильтрует по ключу секции, сканируя только те секции, чьи списки значений пересекаются с фильтром. Секционирование по списку хорошо работает совместно с секцией DEFAULT в PostgreSQL, которая перехватывает строки, чьё значение ключа не совпадает ни с одним из определённых списков.
Как это работает
LIST PARTITION разбивает одну логическую таблицу на много физических партиций: по range (timestamp), list (регионы) или hash (шардинг по id). Каждая партиция — реальная таблица; родительская — routing-слой. Constraint exclusion позволяет планировщику пропускать нерелевантные партиции. Postgres 10+ поддерживает декларативное (PARTITION BY RANGE); pg_partman автоматизирует создание и retention. Особенно полезно для time-series: DROP старых партиций (мгновенно) вместо DELETE (медленно + bloat).
Когда применять
Партиционируйте, когда одна таблица переваливает ~50-100M строк или начинает тянуть maintenance (VACUUM, REINDEX, запросы). Партиционируйте по колонке, по которой чаще всего фильтруете (обычно время). pg_partman — для time-based жизненного цикла. Не партиционируйте преждевременно — на < 10M строк это добавляет операционный overhead без пользы; хорошо настроенных индексов хватает.
Типичные ошибки
Ловушки LIST PARTITION: запросы без partition-ключа в WHERE (планировщик не может прунить — скан всех партиций, медленнее непартиционированного); unique constraint, обязанный охватить все партиции (нужен partition-ключ внутри); ручное создание партиций отстаёт (записи валятся, когда у "сегодня" нет партиции); over-партиционирование (10000 партиций по 100 строк — overhead планировщика затмевает выгоду).