Как заставить Postgres использовать индекс, если в противном случае он настаивал бы на последовательном сканировании?
sql
postgresql
indexing
микрофон
источник
источник
Ответы:
Предполагая, что вы спрашиваете об общей функции «подсказки индекса», которая есть во многих базах данных, PostgreSQL не предоставляет такой возможности. Это было сознательное решение команды PostgreSQL. Хороший обзор того, почему и что вы можете сделать вместо этого, можно найти здесь . Причины в основном в том, что это взлом производительности, который, как правило, вызывает больше проблем позже, когда ваши данные изменяются, тогда как оптимизатор PostgreSQL может повторно оценить план на основе статистики. Другими словами, то, что могло бы быть хорошим планом запроса сегодня, вероятно, не будет хорошим планом запроса на все времена, а подсказки индексов навязывают конкретный план запроса на все времена.
Как очень тупой молоток, полезно для тестирования, вы можете использовать
enable_seqscan
иenable_indexscan
параметры. Видеть:enable_
параметрыОни не подходят для постоянного производственного использования . Если у вас возникли проблемы с выбором плана запроса, вам следует ознакомиться с документацией по отслеживанию проблем с производительностью запроса . Не просто устанавливайте
enable_
параметры и уходите.Если у вас нет веских причин для использования индекса, Postgres может сделать правильный выбор. Зачем?
См. Также это старое сообщение группы новостей .
источник
Вероятно, единственная веская причина для использования
это когда вы пишете запросы и хотите быстро увидеть, каким был бы план запроса, если бы в таблице (ах) были большие объемы данных. Или, конечно, если вам нужно быстро подтвердить, что ваш запрос не использует индекс просто потому, что набор данных слишком мал.
источник
set enable_seqscan=false
, запустите свой запрос, а затем быстро запустите,set enable_seqscan=true
чтобы вернуть postgresql его правильное поведение (и, очевидно, не делайте этого в производственнойSET SESSION enable_seqscan=false
чтобы повлиять только на себяИногда PostgreSQL не может выбрать наилучший индекс для определенного условия. В качестве примера предположим, что есть таблица транзакций с несколькими миллионами строк, из которых несколько сотен на любой день, и таблица имеет четыре индекса: transaction_id, client_id, date и description. Вы хотите выполнить следующий запрос:
PostgreSQL может выбрать использование индекса transaction_description_idx вместо transaction_date_idx, что может привести к тому, что запрос займет несколько минут вместо менее одной секунды. Если это так, вы можете принудительно использовать индекс по дате, подставив условие следующим образом:
источник
your_wanted_index
, возможно, что механизм postgresql просто выполнит вместо этого сканирование последовательности / первичного ключа. Заключение - не существует 100% надежного метода принудительного использования индекса для сервера PostgreSql.where
условия, кроме двух таблиц или соединенных, и Postgres не может принять индекс.Короткий ответ
Эта проблема обычно возникает, когда оценочная стоимость сканирования индекса слишком высока и не соответствует действительности. Вам может потребоваться уменьшить
random_page_cost
параметр конфигурации, чтобы исправить это. Из документации Postgres :Вы можете проверить, действительно ли более низкое значение заставит Postgres использовать индекс (но используйте это только для тестирования ):
Вы можете
SET random_page_cost = DEFAULT;
снова восстановить значение по умолчанию, нажав .Задний план
Для сканирования индекса требуется непоследовательная выборка страниц с диска. Postgres использует
random_page_cost
для оценки стоимости таких непоследовательных выборок по сравнению с последовательными выборками. Значение по умолчанию равно4.0
, таким образом, предполагается, что средний коэффициент затрат равен 4 по сравнению с последовательными выборками (с учетом эффектов кэширования).Однако проблема в том, что это значение по умолчанию не подходит в следующих важных реальных сценариях:
1) твердотельные накопители
Как говорится в документации:
Согласно последнему пункту этого слайда из выступления на PostgresConf 2018,
random_page_cost
следует установить что-то среднее1.0
и2.0
для твердотельных накопителей.2) Кешированные данные
Если необходимые данные индекса уже кэшированы в ОЗУ, сканирование индекса всегда будет значительно быстрее, чем последовательное сканирование. В документации говорится:
Проблема в том, что вы, конечно, не можете легко узнать, кэшированы ли уже соответствующие данные. Однако, если конкретный индекс запрашивается часто и если в системе достаточно ОЗУ, данные, скорее всего, будут кэшироваться, и
random_page_cost
их следует установить на более низкое значение. Вам придется поэкспериментировать с разными значениями и посмотреть, что вам подходит.Вы также можете использовать расширение pg_prewarm для явного кэширования данных.
источник
Сам по себе вопрос очень некорректный. Принудительное использование (например, enable_seqscan = off) - очень плохая идея. Было бы полезно проверить, будет ли он быстрее, но производственный код никогда не должен использовать такие уловки.
Вместо этого - объясните анализ вашего запроса, прочтите его и выясните, почему PostgreSQL выбирает плохой (на ваш взгляд) план.
В Интернете есть инструменты, которые помогают с чтением результатов объяснения и анализа - один из них - execute.depesz.com - написанный мной.
Другой вариант - присоединиться к каналу #postgresql в сети freenode irc и поговорить с парнями, чтобы они вам помогли - поскольку оптимизация запроса не сводится к тому , чтобы «задать вопрос, получить ответ и быть счастливым». это больше похоже на беседу, в которой нужно многое проверить и многому научиться.
источник
Существует трюк, чтобы заставить postgres предпочесть seqscan, добавив
OFFSET 0
в подзапросЭто удобно для оптимизации запросов, связывающих большие / огромные таблицы, когда все, что вам нужно, это только n первых / последних элементов.
Допустим, вы ищете первые / последние 20 элементов, включающих несколько таблиц, содержащих 100 тыс. (Или более) записей, без создания / связывания всего запроса по всем данным, когда то, что вы будете искать, находится в первых 100 или 1000 записи. В этом случае, например, последовательное сканирование оказывается более чем в 10 раз быстрее.
см. Как я могу запретить Postgres встраивать подзапрос?
источник