Кейс: индекс существовал, но Postgres его не использовал

В одном проекте запрос с JOIN по user_id внезапно перешёл с Index Scan на Seq Scan после рефакторинга слоя доступа к данным — без изменений в SQL и без изменений в индексах.

EXPLAIN ANALYZE показал причину: параметр, который раньше передавался как bigint, стал приходить как text из-за смены типа поля в DTO. Planner добавил неявный cast ::text к колонке user_id, чтобы сравнить типы — и индекс на bigint-колонке для сравнения через cast не подошёл.

Исправили тип параметра на bigint на уровне маппинга — Index Scan вернулся без изменений в SQL и без пересборки индекса.

Ловушка в том, что запрос не менялся вообще — ломается совместимость типов на границе ORM. Планировщик молчит, EXPLAIN — единственный способ увидеть implicit cast.

Неявный cast невидим в коде — видим только в плане запроса.

Тренажёр: 600 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки