PostgreSQL как вариации производительности запросов

Я видел довольно большой разброс во времени отклика относительно LIKE запросы к определенной таблице в базе данных. Иногда я получаю результаты в течение 200-400 мс (очень приемлемо), но в других случаях может потребоваться до 30 секунд, чтобы вернуть результаты.

Я понимаю, что LIKE запросы очень ресурсоемки, но я просто не понимаю, почему будет такая большая разница во времени ответа. Я построил индекс btree на

6 ответов


FTS не поддерживает LIKE

на ранее принятый ответ был неверным. Полнотекстовый Поиск С его полнотекстовыми индексами является не на LIKE оператор вообще, он имеет свои собственные операторы и не работает для произвольных строк. Он работает на слова на основе словарей и вытекающие. Это тут поддержка префикс, соответствующий словам, а не LIKE оператор:

индексы триграммы для LIKE

установить дополнительный модуль pg_trgm, который предоставляет классы для оператора индексы джина и триграммы в поддержку все LIKE и ILIKE шаблоны, а не только левые якоря:

пример индекс:

CREATE INDEX tbl_col_gin_trgm_idx  ON tbl USING gin  (col gin_trgm_ops);

или:

CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);

запрос:

SELECT * FROM tbl WHERE col LIKE '%foo%';   -- leading wildcard
SELECT * FROM tbl WHERE col ILIKE '%foo%';  -- works case insensitively as well

триграмм? А как насчет коротких струн?

слова менее 3 букв в индексированных значениях все еще работают. инструкции:

каждое слово считается с двумя пробелами и одним пробелом суффикс при определении набор триграмм, содержащихся в строке.

и шаблоны поиска с менее чем 3 буквами? инструкции:

как LIKE и поиск регулярных выражений, имейте в виду, что a шаблон без извлекаемых триграмм вырождается в полноиндексное сканирование.

означает, что сканирование индекса / растрового изображения все еще работает (планы запросов для подготовленного оператора не будут нарушены), он просто не купит вам лучше спектакль. Как правило, без больших потерь, поскольку строки из 1 или 2 букв вряд ли являются выборочными (более нескольких процентов совпадений с базовой таблицей), а поддержка индекса не улучшит производительность, потому что полное сканирование таблицы происходит быстрее.


text_pattern_ops по префиксу

только слева-якорь шаблоны (без ведущего подстановочного знака) вы получаете оптимальный вариант с подходящим оператор класс для btree индекс: text_pattern_ops или varchar_pattern_ops. Обе встроенные функции стандартных Postgres, не требуется дополнительный модуль. Аналогичная производительность, но гораздо меньший индекс.

пример индекса:

CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);

запрос:

SELECT * FROM tbl WHERE col LIKE 'foo%';  -- no leading wildcard

или, если вы должны запускать свою базу данных с помощью 'C' locale (эффективно нет locale), то все сортируется в соответствии с порядком байтов в любом случае и простым индексом btree по умолчанию класс оператора выполняет эту работу.

более подробная информация, объяснение, примеры и ссылки в этих связанных ответах на dba.SE:


возможно, быстрые-это закрепленные шаблоны с учетом регистра, которые могут использовать индексы. т. е. в начале строки соответствия нет дикой карты, поэтому исполнитель может использовать сканирование диапазона индексов. (соответствующий комментарий в документах здесь) Lower и ilike также потеряют вашу способность использовать индекс, Если вы специально не создадите индекс для этой цели (см. функциональные показатели).

Если вы хотите найти строку в середине поле, вы должны посмотреть в полный текст или триграмма индексы. Первый из них находится в ядре Postgres, другой доступен в модулях contrib.


вы можете установить Wildspeed другой тип индекса в PostgreSQL. Wildspeed работает с% word % wildcards, без проблем. Недостатком является размер индекса, он может быть большим, очень большим.


пожалуйста, выполните ниже упомянутый запрос для улучшения производительности запроса LIKE в postgresql. создать такой индекс для больших таблиц:

CREATE INDEX <indexname> ON <tablename> USING btree (<fieldname> text_pattern_ops)

ваши подобные запросы, вероятно, не могут использовать созданные вами индексы, потому что:

1) Ваши критерии LIKE начинаются с подстановочного знака.

2) вы использовали функцию с критериями.


чего бы это ни стоило,Джанго ORM имеет тенденцию использовать UPPER(text) для всех LIKE запросов, чтобы сделать его нечувствительным к регистру,

добавление индекса на UPPER(column::text) значительно ускорило мою систему, в отличие от любой другой вещи.

что касается ведущего %, Да, который не будет использовать индекс. См. этот блог для отличного объяснения:

https://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-tuning