Как работает связка 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-систем с большими таблицами всегда предпочтительнее явный диапазон таймстампов.
