Событий за день: date_trunc в фильтре и последовательное чтение
PostgreSQL, таблица events на сотни миллионов строк, есть индекс по created_at. Запрос считает события за один день и работает минуты:
SELECT COUNT(*)
FROM events
WHERE date_trunc('day', created_at) = '2026-03-01';
В плане — последовательное чтение таблицы. Почему индекс не используется и что изменить?
- Функция над колонкой не даёт использовать обычный индекс по created_at: планировщику нужно вычислить date_trunc для каждой строки. Условие надо переписать диапазоном: created_at >= '2026-03-01' AND created_at < '2026-03-02'
- Индекс по timestamp не подходит для сравнения с датой: нужно завести отдельную колонку типа date, индексировать её и переписать на неё все запросы по дням: сравнение timestamp с датой всегда приводит к полному чтению, других способов ускорить такой фильтр в PostgreSQL нет
- Для агрегатов индексы не применяются: COUNT(*) всегда требует полного чтения таблицы
- Проблема в неявном приведении строкового литерала: достаточно написать CAST('2026-03-01' AS timestamp), и индекс подхватится
