Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Партиционирование БД

Партиционирование БД: разделы, ключ и обслуживание

Партиционирование таблиц: выбор ключа раздела, сокращение перебора, обслуживание разделов, удаление данных и проверка плана.

Прямой ответ

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

Параметр Что определяет
Ключ раздела Столбец, по которому данные делятся
Число разделов Гранулярность деления
Исключение разделов Доля разделов, исключаемых из чтения
Обслуживание Операции над отдельным разделом
CREATE TABLE events (
    id bigint GENERATED ALWAYS AS IDENTITY,
    created_at timestamptz NOT NULL,
    payload jsonb
) PARTITION BY RANGE (created_at);

CREATE TABLE events_2026_10 PARTITION OF events
    FOR VALUES FROM ('2026-10-01') TO ('2026-11-01');

Условие по ключу раздела исключает разделы вне диапазона, поэтому объём чтения определяется размером раздела, а не размером таблицы. О шардировании — в статье про шардирование БД.

Выбор ключа раздела и исключение разделов

Ключ раздела определяет, какие данные попадают в какой раздел, поэтому условие запроса по ключу сокращает объём чтения.

Ключ по диапазону. Данные делятся по диапазону значений, поэтому запрос с условием по диапазону читает часть разделов.

Ключ по списку. Данные делятся по перечню значений, поэтому запрос с условием по значению читает один раздел.

Исключение разделов. Планировщик исключает разделы, не попадающие под условие, поэтому объём чтения сокращается.

Практическое следствие: запрос без условия по ключу раздела читает все разделы, поэтому объём чтения равен объёму всей таблицы и выигрыш отсутствует.

Отдельный аспект — распределение данных по разделам. Неравномерное распределение приводит к тому, что один раздел содержит основную долю строк, поэтому запрос, попадающий в этот раздел, читает объём, близкий к объёму всей таблицы.

Обслуживание разделов и удаление данных

Раздел обслуживается как отдельный объект, поэтому операции над разделом не затрагивают остальные разделы.

Удаление раздела. Раздел удаляется как отдельный объект, поэтому удаление выполняется быстрее, чем удаление строк из таблицы.

Архивация раздела. Раздел переносится в хранилище без удаления остальных разделов, поэтому доступ к текущим данным сохраняется.

Индекс раздела. Индекс раздела строится отдельно, поэтому построение не блокирует чтение остальных разделов.

Практическое следствие: удаление устаревших строк оператором DELETE требует обработки каждой строки, поэтому операция выполняется дольше, чем удаление раздела.

Проверка плана и влияние на запрос

План запроса показывает, какие разделы читаются, поэтому эффект партиционирования подтверждается по плану.

Исключение разделов в плане. План перечисляет разделы, участвующие в чтении, поэтому доля исключённых разделов видна явно.

Чтение всех разделов. План, перечисляющий все разделы, указывает на отсутствие условия по ключу, поэтому выигрыш отсутствует.

Индекс внутри раздела. Индекс раздела применяется к чтению раздела, поэтому условие по столбцу вне ключа раздела использует индекс раздела.

Практическое следствие: план без исключения разделов показывает, что партиционирование не даёт сокращения объёма чтения для этого запроса.

О репликах для чтения — в статье про read replicas; об индексах — в статье про индексы PostgreSQL.

Практика: настройка партиционирования

1. Выбирайте ключ раздела по фактическим условиям запроса. Условие по ключу исключает разделы, поэтому объём чтения сокращается.

2. Проверяйте распределение данных по разделам. Неравномерное распределение делает один раздел основным по объёму.

3. Создавайте разделы заранее. Раздел для нового диапазона создаётся до появления данных, поэтому запись не прерывается.

4. Удаляйте устаревшие данные удалением раздела. Удаление раздела выполняется быстрее, чем удаление строк оператором DELETE.

5. Стройте индексы разделов отдельно. Построение индекса раздела не блокирует чтение остальных разделов.

6. Проверяйте план запроса после партиционирования. Исключение разделов в плане подтверждает сокращение объёма чтения.

7. Фиксируйте объём разделов в метриках. Рост объёма раздела указывает на изменение распределения данных.

Рекомендации:

  1. Не партиционируйте таблицу без условия по ключу в запросах. Запрос без условия по ключу читает все разделы, поэтому выигрыш отсутствует.
  2. Учитывайте распределение данных при выборе ключа. Неравномерное распределение снижает эффект от деления.
  3. Сопоставляйте размер раздела с объёмом запроса. Раздел, содержащий основную долю строк, не даёт сокращения объёма.
  4. Фиксируйте число разделов в обслуживании. Рост числа разделов увеличивает объём служебных операций.
  5. Пересматриваем ключ раздела при изменении запросов. Новый запрос может требовать иного ключа раздела.

Практический сценарий: партиционирование не ускорило запрос

Контекст: таблица была разделена на разделы по дате, но время запроса не сократилось, поэтому эффект отсутствовал.

  1. Диагностика. План запроса перечислял все разделы. Условие запроса применялось к столбцу, не входящему в ключ раздела, поэтому исключение разделов не выполнялось.
  2. Причина. Ключ раздела не соответствовал фактическим условиям запроса, поэтому планировщик читал все разделы.
  3. Действия. (а) Проверили условия фактических запросов и выбрали ключ раздела по столбцу, участвующему в фильтре; (б) пересоздали разделы по новому ключу, чтобы данные распределились равномерно; (в) сняли повторный план и убедились в исключении разделов; (г) сравнили фактическое время до и после изменения и зафиксировали сокращение; (д) настроили удаление устаревших данных удалением раздела, чтобы обслуживание выполнялось быстрее.
  4. Результат. Запрос читает часть разделов, поэтому объём чтения сократился и время ответа уменьшилось.

Вывод: партиционирование сокращает объём чтения только при условии по ключу раздела, поэтому запрос без такого условия читает все разделы. Выбор ключа по фактическим условиям запроса обеспечивает исключение разделов в плане.

FAQ

Что даёт партиционирование таблицы? Запрос с условием по ключу раздела читает часть данных вместо всей таблицы, поэтому объём чтения сокращается.

Как выбрать ключ раздела? По фактическим условиям запроса. Условие по ключу исключает разделы, поэтому ключ выбирается по столбцу, участвующему в фильтре.

Почему партиционирование не ускоряет запрос? Отсутствие условия по ключу раздела приводит к чтению всех разделов, поэтому объём чтения равен объёму всей таблицы.

Как удалять устаревшие данные? Удалением раздела как отдельного объекта. Операция выполняется быстрее, чем удаление строк оператором DELETE.

Источники: PostgreSQL DDL partitioning, partition maintenance, partitioned tables — ссылки в шапке.