Краткий ответ
Эта проблема обычно возникает, когда оценочная стоимость сканирования индекса слишком высока и не соответствует действительности. Вам может потребоваться уменьшить параметр конфигурации random_page_cost
, чтобы это исправить. Из документации Postgres :
Уменьшение этого значения [...] приведет к тому, что система предпочтет сканирование индекса; его увеличение сделает просмотр индекса относительно более дорогим.
Вы можете проверить, действительно ли более низкое значение заставит Postgres использовать индекс (но используйте его только для тестирования ):
EXPLAIN <query>; # Uses sequential scan
SET random_page_cost = 1;
EXPLAIN <query>; # May use index scan now
Вы можете восстановить значение по умолчанию с помощью SET random_page_cost = DEFAULT;
снова.
Фон
Сканирование индекса требует непоследовательного извлечения страницы на диске. Postgres использует random_page_cost
для оценки стоимости таких непоследовательных выборок по сравнению с последовательными выборками. Значение по умолчанию - 4.0
, что предполагает коэффициент стоимости , равный 4 по сравнению с последовательными выборками (с учетом эффектов кэширования).
Однако проблема в том, что это значение по умолчанию не подходит для следующих важных реальных сценариев:
1) Твердотельные накопители
Хранилище с низкой стоимостью случайного чтения по сравнению с последовательным, например Твердотельные накопители могут быть лучше смоделированы с меньшим значением для random_page_cost
.
Согласно этого слайда из выступления на PostgresConf 2018, random_page_cost
должно быть установлено на 2.0
или ниже для твердотельных накопителей.
2) Сильно кэшированные данные
Соответственно, если ваши данные, вероятно, будут полностью в кеше, [...] может быть целесообразным уменьшение random_page_cost
.
Если вы знаете, что индекс полностью кэшируется в ОЗУ (для этого вы также можете использовать расширение pg_prewarm ), для random_page_cost
следует даже установить 1.0
.