HASH PARTITION
Тема дорожной карты · PostgreSQL
Хэш-секционирование — стратегия секционирования таблиц в PostgreSQL, при которой строки распределяются по фиксированному числу дочерних секций путём применения хэш-функции к одному или нескольким столбцам ключа секции. Каждой дочерней секции назначаются модуль и остаток, поэтому PostgreSQL направляет строку в секцию, остаток которой совпадает с хэшем значения ключа этой строки, обеспечивая равномерное распределение данных по секциям. Хэш-секционирование особенно полезно для больших таблиц реляционных баз данных, в которых нет естественных границ диапазонов или списков, а основная цель — балансировка нагрузки между хранилищами или параллельными рабочими потоками запросов. При выполнении SQL-запроса с фильтром по ключу секции планировщик PostgreSQL может выполнить отсечение секций и пропустить те, чей хэш-остаток не может совпасть с фильтром, снижая объём операций ввода-вывода. Выбор подходящего числа секций заранее важен, поскольку изменение модуля при хэш-секционировании требует пересоздания структуры секций.
Как это работает
HASH 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 без пользы; хорошо настроенных индексов хватает.
Типичные ошибки
Ловушки HASH PARTITION: запросы без partition-ключа в WHERE (планировщик не может прунить — скан всех партиций, медленнее непартиционированного); unique constraint, обязанный охватить все партиции (нужен partition-ключ внутри); ручное создание партиций отстаёт (записи валятся, когда у "сегодня" нет партиции); over-партиционирование (10000 партиций по 100 строк — overhead планировщика затмевает выгоду).