Секционирование таблиц в PostgreSQL: Declarative Partitioning по Range и List
- Деградация производительности при вставке и поиске в таблицах размером свыше 100 млн записей.
- Длительное время создания индексов и блокировки при операциях
VACUUMиREINDEX. - Сложности с удалением устаревших исторических данных (архивация через медленный
DELETE).
1. Создание секционированной таблицы по диапазонам (RANGE)
CREATE TABLE measurements (
id BIGINT GENERATED ALWAYS AS IDENTITY,
log_time TIMESTAMPTZ NOT NULL,
device_id INT NOT NULL,
metric_value NUMERIC(10,2),
CONSTRAINT pk_measurements PRIMARY KEY (id, log_time)
) PARTITION BY RANGE (log_time);2. Создание дочерних секций
CREATE TABLE measurements_y2025m01 PARTITION OF measurements
FOR VALUES FROM ('2025-01-01 00:00:00+00') TO ('2025-02-01 00:00:00+00');
CREATE TABLE measurements_y2025m02 PARTITION OF measurements
FOR VALUES FROM ('2025-02-01 00:00:00+00') TO ('2025-03-01 00:00:00+00');
-- Секция по умолчанию для предотвращения ошибок вставки
CREATE TABLE measurements_default PARTITION OF measurements DEFAULT;3. Создание секционированной таблицы по спискам (LIST)
CREATE TABLE client_orders (
order_id BIGINT,
region_code VARCHAR(10) NOT NULL,
amount NUMERIC(12,2),
PRIMARY KEY (order_id, region_code)
) PARTITION BY LIST (region_code);
CREATE TABLE client_orders_eu PARTITION OF client_orders FOR VALUES IN ('EU-WEST', 'EU-CENTRAL');
CREATE TABLE client_orders_us PARTITION OF client_orders FOR VALUES IN ('US-EAST', 'US-WEST');4. Проверка работы отсечения секций (Partition Pruning)
Убедитесь, что оптимизатор исключает ненужные партиции:
SET enable_partition_pruning = on;
EXPLAIN SELECT * FROM measurements
WHERE log_time >= '2025-01-15' AND log_time < '2025-01-20';5. Мгновенное удаление архивных данных
ALTER TABLE measurements DETACH PARTITION measurements_y2025m01;
DROP TABLE measurements_y2025m01; Частые вопросы (FAQ)
Почему первичный ключ должен обязательно включать ключ секционирования?
PostgreSQL строит уникальные ограничения и индексы отдельно для каждой партиции. Чтобы гарантировать глобальную уникальность ключа без сканирования всех секций, ключ партиционирования обязан входить в состав PRIMARY KEY.
Что такое Partition Pruning и как проверить его работу?
Это механизм планировщика, исключающий нерелевантные секции из плана запроса на этапе планирования или выполнения. В EXPLAIN анализе будет виден скан только конкретной партиции, а не всей структуры.
Поддерживается ли автоматическое создание новых партиций в PostgreSQL?
В ядре PostgreSQL декларативное создание автоматических будущих секций 'из коробки' отсутствует. Для автоматизации создания партиций используют расширение pg_partman или триггерные механизмы.
Как влияет DEFAULT партиция на последующее добавление новых секций?
Если DEFAULT секция содержит строки, попадающие в диапазон новой создаваемой партиции, команда ATTACH/CREATE PARTITION завершится ошибкой. Потребуется предварительно переместить конфликтующие данные.