Фильтр по функции над колонкой отключил отсечение секций
Таблица dds.fct_events в PostgreSQL — 800 млн строк, секционирована по месяцам колонки event_ts (timestamp), по этой же колонке есть индекс. Отчёт за один день собирается шесть минут, в плане — последовательное чтение всех секций:
SELECT count(*)
FROM dds.fct_events
WHERE to_char(event_ts, 'YYYY-MM-DD') = '2026-08-01';
У коллеги похожий отчёт за тот же день отрабатывает за секунды. В чём причина и как переписать условие?
- Дело в статистике: планировщик не знает селективность выражения и считает, что условие вернёт значительную часть таблицы; после ANALYZE и увеличения детальности статистики по event_ts он переключится на чтение по индексу.
- Отсечение секций работает только при явном обращении к нужной секции: запрос к родительской таблице всегда читает все части, поэтому отчёт надо направлять прямо в fct_events_2026_08.
- Колонка завёрнута в функцию, поэтому предикат не сопоставляется ни с ключом секционирования, ни с индексом по event_ts. Условие надо записать диапазоном по самой колонке: event_ts >= '2026-08-01' AND event_ts < '2026-08-02'.
- Причина в форматирующей функции: to_char возвращает text, и сравнение идёт по строке. Достаточно заменить её на приведение типа event_ts::date = '2026-08-01' — приведение планировщик разворачивает в диапазон, и отсечение заработает.
