Создать таблицу с помесячным range-секционированием (генерация секций в цикле)
PostgreSQLСекционированиеКоманда
CREATE TABLE sales (
id bigint GENERATED ALWAYS AS IDENTITY,
created_at date NOT NULL,
customer_id bigint NOT NULL,
amount numeric(12,2),
PRIMARY KEY (id, created_at)
) PARTITION BY RANGE (created_at);
-- An index defined on the parent propagates to all partitions automatically
CREATE INDEX sales_customer_id_idx ON sales (customer_id);
-- 12 monthly partitions for 2026
DO $$
DECLARE
m date;
BEGIN
FOR m IN SELECT generate_series(date '2026-01-01', date '2026-12-01', interval '1 month')::date LOOP
EXECUTE format(
'CREATE TABLE IF NOT EXISTS %I PARTITION OF sales FOR VALUES FROM (%L) TO (%L)',
'sales_' || to_char(m, 'YYYY_MM'), m, (m + interval '1 month')::date);
END LOOP;
END $$;
-- Hierarchy, bounds and sizes
SELECT t.relid::regclass AS partition_name,
t.parentrelid::regclass AS parent,
t.isleaf,
t.level,
pg_get_expr(c.relpartbound, c.oid) AS bounds,
pg_size_pretty(pg_total_relation_size(t.relid)) AS total_size
FROM pg_partition_tree('sales') t
JOIN pg_class c ON c.oid = t.relid
ORDER BY t.level, bounds;Что делает
Создаёт родительскую таблицу с секционированием RANGE по столбцу даты, индекс, распространяющийся на все секции, и 12 помесячных секций в цикле; затем выводит иерархию с границами и размерами.
Когда использовать
Для больших, постоянно растущих таблиц, из которых периодически удаляются старые данные (DETACH/DROP) или запросы к которым в основном фильтруют по диапазону дат (заказы, журналы, временные ряды).
Внимание
В секционированной таблице ограничения PRIMARY KEY/UNIQUE должны включать ключ секционирования (глобальных уникальных индексов нет). Нижняя граница включается, верхняя — нет (FROM inclusive, TO exclusive). Без задания, заранее создающего будущие секции (pg_cron, pg_partman), INSERT вне диапазона завершаются ошибкой. Тысячи секций увеличивают время планирования и накладные расходы на блокировки. CREATE INDEX CONCURRENTLY на родительской таблице не поддерживается: используйте CREATE INDEX ... ON ONLY на родителе, CREATE INDEX CONCURRENTLY на каждой секции, затем ALTER INDEX ... ATTACH PARTITION.
Связанные материалы
- Подключить подготовленную таблицу как секцию с короткой блокировкой (ATTACH PARTITION)
- Отключить старую секцию, не блокируя рабочий трафик (DETACH CONCURRENTLY)
- Ловушка секции по умолчанию: создание новой секции завершается ошибкой 'would be violated by some row'
- Проверить, что работает отсечение секций (partition pruning) на этапе планирования и выполнения
- Автоматизировать создание секций и их хранение через pg_partman