Влияние на производительность пустого LIKE в подготовленном операторе

Я установил индекс GiST pg_trgm для столбца name таблицы files. .

Упрощенный запрос подготовленного оператора выглядит так:

SELECT * FROM files WHERE name LIKE $1;

Параметр $1 будет состоять из % + пользовательский запрос + %. Поскольку ввод также может быть пустой строкой, это может привести к %%.

Приводит ли «пустой» LIKE (%%) к снижению производительности? Должен ли я создать новый запрос в этом случае, или это не имеет значения?


person Erik Aigner    schedule 25.09.2013    source источник
comment
Проверьте план выполнения, и вы узнаете   -  person a_horse_with_no_name    schedule 25.09.2013
comment
Спросил бы я, знаю ли я, как использовать/читать планы выполнения?   -  person Erik Aigner    schedule 25.09.2013
comment
Тогда самое время начать изучать следующее: postgresql.org/docs /current/static/using-explain.html и postgresql .org/docs/current/static/sql-explain.html   -  person a_horse_with_no_name    schedule 25.09.2013
comment
@ErikAigner Empty like (name LIKE '%%') по-прежнему будет отфильтровывать строки, где name is null. Если вы вообще не хотите фильтровать - добавьте or length(user_query) = 0.   -  person Ihor Romanchenko    schedule 25.09.2013


Ответы (1)


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
comment
Делал это уже, но cost по-прежнему казался немного выше с LIKE. - person Erik Aigner; 25.09.2013
comment
Таким образом, стоимость кажется 0.1 выше с LIKE, что, я думаю, незначительно. - person Erik Aigner; 25.09.2013
comment
Первые два запроса равны, только если name is not null. - person Ihor Romanchenko; 25.09.2013
comment
name в моем случае всегда не равно null - person Erik Aigner; 25.09.2013
comment
@IgorRomanchenko: Вы были правы насчет случая NULL. К настоящему времени я полностью переписал ответ с более конкретной информацией. - person Erwin Brandstetter; 25.09.2013