Выбор ответа Middle Индексы обновлено

Почему индекс по created_at не используется

Вопрос

Есть B-tree индекс orders_created_at_idx по created_at. Почему в плане нет обращения к нему?

Gather  (cost=1000.00..16199.67 rows=5000 width=32) (actual time=18.035..56.183 rows=2880 loops=1)
  Workers Planned: 2
  Workers Launched: 2
  ->  Parallel Seq Scan on orders  (cost=0.00..14699.67 rows=2083 width=32) (actual time=20.416..43.039 rows=960 loops=3)
        Filter: (date((created_at AT TIME ZONE 'UTC'::text)) = '2024-03-01'::date)
        Rows Removed by Filter: 332373
Planning Time: 0.477 ms
Execution Time: 56.398 ms

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: Колонка завёрнута в функцию, а индекс хранит сами значения. Индекс применим, когда условие имеет вид «индексированное выражение, оператор, значение».

Варианты ответа

  1. Колонка завёрнута в функцию, а индекс хранит сами значенияправильный ответ
  2. Параллельные воркеры не читают индексы, и выбран параллельный план
  3. Под условие попадает больше половины таблицы, Seq Scan дешевле
  4. Индекс по timestamptz не подходит для сравнения с типом date

Разбор

Индекс применим, когда условие имеет вид «индексированное выражение, оператор, значение». Здесь в условии date(created_at AT TIME ZONE 'UTC'), которого в индексе нет, и планировщику остаётся только читать всё и считать функцию для каждой строки (Rows Removed by Filter). Решения два: переписать фильтр диапазоном created_at >= '2024-03-01' AND created_at < '2024-03-02' (в нужной зоне) или создать индекс по тому же выражению. Параллельные планы умеют и Parallel Index Scan. Под фильтр попадает 2880 строк из миллиона, так что дело не в селективности. Сравнение timestamptz с date индекс тоже поддерживает: значение приводится к типу колонки.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.