PostgreSQL как вариации производительности запросов
Я видел довольно большое изменение времени отклика относительно LIKE
запросы к определенной таблице в базе данных. Иногда я получаю результаты в течение 200-400 мс (очень приемлемо), но в других случаях это может занять до 30 секунд, чтобы вернуть результаты.
Я понимаю, что LIKE
запросы очень ресурсоемкие, но я просто не понимаю, почему будет такая большая разница во времени отклика. Я построил индекс btree на
6 ответов:
FTS не поддерживает
LIKE
The ранее принятый ответ был неверным. Полнотекстовый Поиск С его полнотекстовыми индексами это не на
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, без проблем. Недостатком является размер индекса, это может быть большой, очень большой.
пожалуйста, выполните указанный ниже запрос для улучшения производительности подобных запросов в postgresql. создать такой индекс для больших таблиц:
CREATE INDEX <indexname> ON <tablename> USING btree (<fieldname> text_pattern_ops)
ваши подобные запросы, вероятно, не могут использовать созданные вами индексы, потому что:
1) Ваши подобные критерии начинаются с подстановочного знака.
2) вы использовали функцию с критериями.
чего бы это ни стоило,Джанго ORM имеет тенденцию использовать
UPPER(text)
для всехLIKE
запросов, чтобы сделать его нечувствительным к регистру,добавление индекса на
UPPER(column::text)
значительно ускорило мою систему, в отличие от любой другой вещи.что касается ведущего %, Да, что не будет использовать индекс. Смотрите этот блог для отличного объяснения:
https://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-tuning
Comments