⚠️ Важная информация Все материалы, инструкции, команды и скрипты предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, баз данных и сетевого оборудования. Перед выполнением действий обязательно создайте резервную копию. При отсутствии необходимой квалификации обратитесь к ИТ-специалистам.
PG_PARTITION_MISCONFIG Linux / DevOps

Декларативное секционирование таблиц в PostgreSQL: RANGE, LIST и HASH

Обновлено: 24.08.2026
  • Размер таблицы превышает сотни гигабайт, приводя к деградации построения B-Tree индексов и медленному VACUUM.
  • Удаление старых архивных данных через DELETE WHERE created_at < ... генерирует терабайты WAL и колоссальный Bloat.
  • Планировщик сканирует всю таблицу целиком вместо выборки конкретного временного интервала.

1. Создание секционированной таблицы по диапазону дат (RANGE)

CREATE TABLE measurements (
    id uuid DEFAULT gen_random_uuid(),
    device_id int NOT NULL,
    measured_at timestamptz NOT NULL,
    value numeric(10,2)
) PARTITION BY RANGE (measured_at);

2. Создание секций и дефолтного раздела

-- Секция за Октябрь 2023
CREATE TABLE measurements_y2023m10 PARTITION OF measurements
    FOR VALUES FROM ('2023-10-01 00:00:00+00') TO ('2023-11-01 00:00:00+00');

-- Секция за Ноябрь 2023
CREATE TABLE measurements_y2023m11 PARTITION OF measurements
    FOR VALUES FROM ('2023-11-01 00:00:00+00') TO ('2023-12-01 00:00:00+00');

-- Секция по умолчанию для предотвращения ошибок вставки не попавших значений
CREATE TABLE measurements_default PARTITION OF measurements DEFAULT;

3. Проверка механизма исключения разделов (Partition Pruning)

Убедитесь, что в postgresql.conf включен параметр enable_partition_pruning = on.

EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM measurements 
WHERE measured_at >= '2023-10-15' AND measured_at < '2023-10-20';

В плане выполнения должно присутствовать сканирование только партиции measurements_y2023m10 (0 partitions scanned for other tables).

4. Безопасное отсоединение старых данных без блокировки

ALTER TABLE measurements DETACH PARTITION measurements_y2023m10 CONCURRENTLY;
DROP TABLE measurements_y2023m10;
Практический опыт инженера: Не создавайте тысячи мелких партиций (например, посуточно на 10 лет вперед). Оптимальное количество активных секций для планировщика PostgreSQL — от нескольких десятков до нескольких сотен.

Частые вопросы (FAQ)

Почему первичный ключ (PRIMARY KEY) в секционированной таблице должен включать ключ партиционирования?

PostgreSQL проверяет уникальность локально внутри каждой партиции. Без включения ключа разбиения в состав PRIMARY KEY ядро не сможет гарантировать уникальность строки по всей таблице.

В чем преимущество DETACH PARTITION CONCURRENTLY?

Оно исключает захват эксклюзивной блокировки AccessExclusiveLock на родительскую таблицу, позволяя выполнять отсоединение устаревших партиций на лету без прерывания пользовательских запросов.

Telegram Telegram Max Max Позвонить Позвонить E-mail E-mail