Почти такой же - за 0,66 мс.
Разница в 451 раз из-за одной строки.
Ситуация обычная: cursor pagination, сортировка по
date DESC, id DESC, лимит на 1000 записей и composite index по (date, id). На первый взгляд, все должно работать быстро.Но
EXPLAIN ANALYZE показывает другое: Postgres вроде бы использует Index Scan, но после этого выкидывает 900 000 строк через Filter.То есть индекс есть, но запрос все равно тащит слишком много лишнего.
Проблема в условии:
`date < @date OR (date = @date AND id <= @lastId)`Для разработчика это выглядит логично: сначала сравниваем дату, потом id.
Но для оптимизатора такой
OR плохо ложится на composite index. В итоге база не может сразу пойти по нужному диапазону и вынуждена фильтровать огромный кусок данных.Правильнее записать условие через tuple comparison:
`(date, id) <= (@date, @lastId)`Смысл тот же, но для Postgres это уже понятный диапазон по составному индексу.
И результат: 298 мс превращаются в 0,66 мс.
Индекс сам по себе ничего не гарантирует.
Важно не только создать индекс, но и написать запрос так, чтобы оптимизатор реально смог его использовать.
