Условие сканирования индекса:
(((center_code)::text = 'IND110030AAC'::text) AND
(created_on >= '2018-10-09 18:30:00+00'::timestamp with time zone) AND
((status)::text = 'Scheduled'::text))
, но само сканирование индекса превышает (center_code, created_on)
, а условие status
применяется в качестве фильтра.
К сожалению, это не видно из плана выполнения, но это следует из следующего правила:
Сканирование индекса будет использовать условия только в том случае, если строки, удовлетворяющие этим условиям, находятся рядом друг с другом в индексе.
Давайте рассмотрим этот пример (в порядке индекса):
center_code | created_on | status
--------------+---------------------+-----------
IND110030AAC | 2018-10-09 00:00:00 | Scheduled
IND110030AAC | 2018-10-09 00:00:00 | Xtra
IND110030AAC | 2018-10-10 00:00:00 | New
IND110030AAC | 2018-10-10 00:00:00 | Scheduled
IND110030AAC | 2018-10-11 00:00:00 | New
IND110030AAC | 2018-10-11 00:00:00 | Scheduled
Вы увидите, что для запроса нужны 4-я и 6-я строки.
PostgreSQL не может сканировать индекс со всеми тремя условиями, поскольку необходимые строки не расположены рядом друг с другом. Он должен будет сканировать только с первыми двумя условиями, потому что все строки, удовлетворяющие этим, находятся рядом друг с другом.
Ваше правило для многостолбцовых индексов неверно. Столбцы слева от индекса должны быть теми, в которых =
используется в качестве оператора сравнения в условиях.
Идеальный индекс будет один на (center_code, status, created_on)
.