Рис. 5.5
План выполнения, использующий индекс
В планах выполнения видно, что стоимость плана с доступом на основе
индекса в два с лишним раза меньше, чем при последовательном скани-
ровании (13857,42 против 30474,52). Что более важно, время выполнения
подтверждает это наблюдение: 0,5 секунды для доступа на основе индекса
против 1,5 секунды для последовательного сканирования.
Индексы и неравенства
77
Обратите пристальное внимание на этот пример. Когда вы читаете о нем
в книге, предыдущий абзац кажется очевидным. Однако многие разработ-
чики SQL и составители отчетов продолжают использовать похожие условия
поиска. Один из частых случаев – поиск изменений, внесенных в таблицу за
сегодняшний день. В девяноста пяти процентах случаев это условие формули-
руют как
update_ts::date
=
CURRENT_DATE
, фактически лишаясь индекса по столб-
цу
update_ts
. Чтобы воспользоваться индексом, критерий следует записать как
update_ts >= CURRENT_DATE,
или, если значения могут быть в будущем, условие должно быть написано
так:
update_ts >= CURRENT_DATE AND update_ts < CURRENT_DATE + 1.
Рассмотрим еще один пример, когда преобразование столбца часто оста-
ется незаметным. Допустим, сегодня 17 августа 2020 г. Мы ищем рейсы, ко-
торые вылетели или запланированы на сегодня. Мы знаем, что для рейсов,
которые еще не вылетели, столбец
actual_departure
может иметь неопреде-
ленное значение.
Функция
coalesce
в PostgreSQL позволяет нам использовать другое значе-
ние, когда первый аргумент неопределен. Таким образом,
coalesce(actual_
departure,
schedule_departure)
вернет
actual_departure
, если это значение
отлично от
NULL
, и
schedule_departure
в противном случае. Оба столбца
sched-
ule_departure
и
actual_departure
проиндексированы, и вы можете ожидать,
что эти индексы будут использоваться. Например, посмотрите на план вы-
полнения следующей инструкции SQL, представленный на рис. 5.6:
SELECT * FROM flight
WHERE coalesce(actual_departure, scheduled_departure)
BETWEEN '2020-08-17' AND '2020-08-18'
Рис. 5.6
План с последовательным сканированием при наличии индексов
Почему не используются индексы? Потому что
coalesce
– это функция,
которая изменяет значения столбца. Должны ли мы создать еще один функ-
циональный индекс? Это можно сделать, но на самом деле не нужно. Вместо
этого перепишем оператор так, как показано в лис тинге 5.8, что приведет
к плану выполнения, показанному на рис. 5.7.
Листинг 5.8
Запрос, использующий оба индекса
SELECT * FROM flight
WHERE (actual_departure BETWEEN '2020-08-17' AND '2020-08-18')
OR (actual_departure IS NULL
AND scheduled_departure BETWEEN '2020-08-17' AND '2020-08-18')
Do'stlaringiz bilan baham: |