Postgres 9.2 или новее обычно достаточно умен, чтобы понять, что условие
WHERE name LIKE '%%'
не является избирательным и прибегает к последовательному сканированию, игнорируя индекс GiST, даже с подготовленными операторами. Однако вы действительно платите небольшую цену за бесполезное состояние.
В Postgres 9.1 или более ранних версиях я бы создал отдельный запрос для особого случая.
Сравните раздел Примечания для оператора PREPARE
в руководстве для версий 9.1, 9.2 и 9.3.
Подтвердите себя
Подготовьте оператор и запустите EXPLAIN ANALYZE
для проверки:
PREPARE plan1 (text) AS
SELECT * FROM file
WHERE name LIKE $1;
EXPLAIN ANALYZE EXECUTE plan1('%123%');
EXPLAIN ANALYZE EXECUTE plan1('%%');
Планы обычно кэшируются на время сеанса.
Альтернативный запрос
Независимо от версии, которую вы используете, если вы всегда выполняете полнотекстовый поиск (подстановочные знаки слева и справа), этот запрос должен быть быстрее для подготовленного оператора:
SELECT * FROM files WHERE name LIKE ('%' || $1 || '%');
И, конечно же, передать шаблон без дополнительных подстановочных знаков (%
). Таким образом, Postgres знает, что во время планирования следует ожидать шаблон, заключенный в подстановочные знаки.
-›демонстрация SQLfiddle.
Обратите внимание на последовательное сканирование пустого LIKE и разницу в производительности между двумя планами.
SQLfiddle сильно различается в зависимости от нагрузки и т. д. Однократное выполнение может быть ненадежным. Лучше протестируйте в своей среде и запустите каждую инструкцию пару раз, чтобы заполнить кеш и устранить шум.
person
Erwin Brandstetter
schedule
25.09.2013
name LIKE '%%'
) по-прежнему будет отфильтровывать строки, гдеname is null
. Если вы вообще не хотите фильтровать - добавьтеor length(user_query) = 0
. - person Ihor Romanchenko   schedule 25.09.2013