Партицированные таблицы в EXPLAIN
Как Append показывает работу с партициями, почему нужен partition pruning и что происходит без фильтра по ключу партиционирования.
PostgreSQLEXPLAINПартиционированиеПроизводительностьЛена подошла к столу Макса с новым планом. На этот раз её вид был озадаченным.
— Макс, я смотрю на запрос к нашей таблице events. И план выглядит… как-то странно. Тут появился узел Append, под которым куча Index Scan по разным таблицам. Это нормально?
Макс взглянул на план:
Append (...) -> Index Scan using idx_events_2025_08_dt on events_2025_08 ... -> Index Scan using idx_events_2025_09_dt on events_2025_09 ...— Поздравляю! — улыбнулся он. — Ты столкнулась с тем, как EXPLAIN показывает работу с партицированными таблицами. Это очень хитро устроенная таблица, которая на самом деле состоит из множества разных таблиц. Узел Append в плане это склейка результатов из релевантных партиций. Каких именно — видно по дочерним узлам.
— Я читала об этом, это похоже на шкаф с одинаковыми документами, где каждый ящик — отдельный месяц?
— Отличная аналогия! — кивнул Макс. — И самая главная магия оптимизатора здесь — это отсечение партиций. При правильном запросе Postgres заранее знает, в какие ящики ему нужно заглянуть, а какие можно проигнорировать. Это и есть ключ к производительности.
Макс открыл два примера, чтобы показать разницу.
- “Правильный” запрос с фильтром по ключу партицирования
EXPLAIN SELECT * FROM events WHERE event_date >= '2025-08-15';В плане будет узел Append, но под ним сканируются только те партиции (ящики), которые содержат нужные даты. Например, events_2025_08, events_2025_09 и так далее. Postgres “отсёк” все партиции за июль и более ранние, даже не заглядывая в них. Это называется partition pruning.
- “Неправильный” запрос, который всё портит
— А теперь смотри, — Макс поменял запрос, — если не использовать ключ партицирования в запросе, ну или использовать его не напрямую.
EXPLAIN SELECT * FROM events WHERE date_trunc('month', event_date) = '2025-08-01';Лена нахмурилась:
— План изменился! Теперь под Append сканируются все партиции с 2022 года!
— Именно! — подтвердил Макс. — И это уже плохо для производительности.
— Получается, главный секрет — помочь Postgres понять, какие партиции ему нужны? — спросила Лена.
— Точно!
— А что если мне нужно выбрать все события пользователя? — спросила Лена. — Например: WHERE user_id = 5.
Макс показал ей план:
Append (...) -> Index Scan using idx_events_2022_01_user_id on events_2022_01 ... -> Index Scan using idx_events_2022_02_user_id on events_2022_02 ... -> ... -> Index Scan using idx_events_2025_10_user_id on events_2025_10 ...— Видишь? — пояснил Макс. — Ключ партиционирования — event_date, а фильтр по нему отсутствует. Значит, отсечение партиций не сработает, и Postgres вынужден проходить по каждой партиции отдельно: для каждой — свой Index Scan, а затем результаты «склеиваются» узлом Append. Иногда это будет Parallel Append (если включён параллелизм) или Merge Append при ORDER BY, но суть та же — много мелких сканов вместо одного большого.
— То есть партиции могут даже замедлять? — уточнила Лена.
— Могут, если часто нужен поиск по всем партициям без фильтра по ключу. Лучше сузить диапазон по event_date (например, последние 90 дней), чтобы отсеять лишние партиции. Но выбор схемы партиционирования и вообще «партиционировать или нет» — это отдельная тема.
Что запомнить
-
Фильтр, который совместим с границами партиций, позволяет отсечь лишние дочерние таблицы. Без подходящего условия планировщику обычно приходится рассматривать их все.
-
Следи за функциями над ключом. Если выражение мешает сопоставить условие с границами партиций, перепиши его как диапазон по самому ключу.
-
Проверяй план через
EXPLAIN: смотри, какие партиции остались подAppend, и полеSubplans Removed, если отсечение произошло во время инициализации плана. Все дочерние таблицы в фактической части плана — повод проверить условие и настройкиenable_partition_pruning.
Лена задумчиво кивнула:
— Значит, партицирование — это инструмент, который требует правильного обращения. И EXPLAIN — лучший способ проверить, правильно ли ты его используешь.
— В точку! — подытожил Макс. — Теперь ты знаешь, что Append в плане — это твой друг, который показывает, насколько эффективен твой запрос.