Как работает связка created_at::date в PostgreSQL и почему для больших таблиц лучше использовать сравнение с таймстампом?

В PostgreSQL выражение `created_at::date` — это явное приведение типа `timestamp` (или `timestamptz`) к типу `date`. Оно отбрасывает временну́ю часть и оставляет только дату. Например, `’2024-03-15 14:32:00′::date` даст `’2024-03-15’`. Это удобно для фильтрации записей по дате:

sql
SELECT * FROM orders WHERE created_at::date = ‘2024-03-15’;

**Почему это проблема на больших таблицах?**

Главная проблема в том, что приведение типа применяется к каждой строке таблицы в момент выполнения запроса. Это означает, что PostgreSQL не может использовать обычный B-tree индекс по колонке `created_at`, даже если он существует. Оптимизатор видит функцию над колонкой и вынужден выполнять **Sequential Scan** — полное последовательное чтение таблицы. На таблице с миллионами строк это приводит к значительному замедлению.

**Правильный подход — сравнение с диапазоном таймстампов**

Вместо приведения типа используйте явный диапазон:

sql
SELECT * FROM orders
WHERE created_at >= ‘2024-03-15 00:00:00’
AND created_at = … AND < …` — позволяет использовать индексы и работает быстрее на больших объёмах данных.
— Функциональный индекс — компромисс, если синтаксис с `::date` принципиален.

Для production-систем с большими таблицами всегда предпочтительнее явный диапазон таймстампов.


Задайте вопрос нейросети

Не нашли ответ? Спросите ИИ — он подготовит развёрнутую статью.