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