Партиционирование таблиц
↑ 2.1 PostgreSQL: индексы, транзакции, оптимизация · ← Предыдущая · → Следующая
Зачем это на собесе
Партиционирование помогает управлять огромными таблицами; важно знать виды и подводные камни.
Зачем
- ускорение запросов за счёт partition pruning (читаются только нужные партиции);
- быстрое удаление старых данных:
DROP PARTITIONвместоDELETE+ VACUUM; - меньшие индексы и более эффективное обслуживание (VACUUM по партициям);
- разделение по хранилищам (tablespace).
Порог применения: таблицы на десятки миллионов строк и больше, естественный ключ разбиения (время, тенант).
Виды (декларативное)
| Вид | Ключ | Пример |
|---|---|---|
| RANGE | диапазон значений | по месяцам |
| LIST | список значений | по региону/тенанту |
| HASH | хэш по модулю | равномерное распределение без естественного ключа |
CREATE TABLE events (
id bigint GENERATED ALWAYS AS IDENTITY,
created_at timestamptz NOT NULL,
user_id bigint NOT NULL,
payload jsonb,
PRIMARY KEY (id, created_at) -- ключ партиционирования входит в PK
) PARTITION BY RANGE (created_at);
CREATE TABLE events_2026_09 PARTITION OF events
FOR VALUES FROM ('2026-09-01') TO ('2026-10-01');
CREATE TABLE events_default PARTITION OF events DEFAULT;
CREATE INDEX ON events (user_id, created_at); -- создаётся на всех партицияхОсобенности
- уникальные ограничения и PK должны включать ключ партиционирования;
- внешние ключи на партиционированные таблицы поддерживаются, но ограничения есть;
- запросы обязаны фильтровать по ключу, иначе просматриваются все партиции;
- слишком много партиций (тысячи) увеличивает время планирования;
- есть
DEFAULT-партиция: следите, чтобы она не распухала; - глобальных индексов нет: индексы локальны для каждой партиции.
Обслуживание
-- отсоединить и удалить старую партицию
ALTER TABLE events DETACH PARTITION events_2025_01 CONCURRENTLY;
DROP TABLE events_2025_01;
-- присоединить готовую (сначала CHECK, чтобы не сканировать)
ALTER TABLE events_2026_10 ADD CONSTRAINT c CHECK (created_at >= '2026-10-01' AND created_at < '2026-11-01');
ALTER TABLE events ATTACH PARTITION events_2026_10 FOR VALUES FROM ('2026-10-01') TO ('2026-11-01');Автоматизация: pg_partman, cron/джобы, создавать партиции заранее.
Проверка pruning
EXPLAIN SELECT * FROM events WHERE created_at >= '2026-09-10' AND created_at < '2026-09-11';
-- в плане только events_2026_09Работает при константах и параметрах; для нестандартных выражений — проверяйте план.
Партиционирование против шардирования
Партиционирование — внутри одной БД/сервера. Шардирование — между серверами (Citus, вручную).
Когда не помогает
- нет естественного ключа, по которому фильтруют;
- запросы затрагивают все партиции;
- небольшие таблицы: только усложнение.
Вопросы с ответами
Что такое partition pruning?
Оптимизация: планировщик или исполнитель исключает партиции, которые не могут содержать нужные строки по условию на ключ партиционирования.
Почему первичный ключ должен включать ключ партиционирования?
Уникальность проверяется внутри партиции (нет глобальных индексов): чтобы гарантировать её для всей таблицы, ключ разбиения обязан входить в ограничение.
Как быстро удалить данные за старый месяц?
Отсоединить и удалить партицию:
DETACH PARTITION+DROP TABLE, без построчного удаления и раздувания.