Postgresql ILIKE против TSEARCH

У меня есть запрос с количество тестовых полей что-то вроде этого:

SELECT * FROM some-table
  WHERE field1 ILIKE "%thing%"
     OR field2 ILIKE "%thing"
     OR field3 ILIKE "%thing";

столбцы в значительной степени все varchar(50) или около того. Теперь я понимаю, что для повышения производительности я должен индексировать поля, на которых работает поиск. Должен ли я полностью заменить ILIKE на TSEARCH?

3 ответов


настройка полнотекстового поиска не идентична запросу" содержит". Это связано со словами и т. д., Поэтому вы можете сопоставить " автомобили "с"автомобилем".

Если вы действительно хотите быстрый ILIKE, то никакой стандартный индекс базы данных или FTS не поможет. К счастью, модуль pg_trgm может это сделать.


одна вещь, которая очень важна: НЕТ ИНДЕКСА B-ДЕРЕВА будет когда-нибудь улучшить этот вид поиска:

where field ilike '%SOMETHING%'

Я говорю, что если вы сделаете:

create index idx_name on some_table(field);

только вы улучшите составляет where field like 'something%'. (при поиске значений, начинающихся с некоторого литерала). Таким образом, вы не получите никакой выгоды, добавив обычный индекс в в этом случае.

Если вам нужно улучшить время ответа на поиск, обязательно рассмотрите возможность использования ПОЛНОТЕКСТОВЫЙ ПОИСК.


добавив немного к тому, что сказали другие.

сначала вы не можете использовать индекс, основанный на значении в середине строки. Индексы-это поиск в дереве, и у вас нет способа узнать, будет ли ваш поиск быстрее, чем просто сканирование таблицы, поэтому PostgreSQL по умолчанию будет сканировать seq. Индексы будут использоваться только в том случае, если они соответствуют первый часть строки. Итак:

SELECT * FROM invoice
  WHERE invoice_number like 'INV-2012-435%'

может использовать индекс, но like '%44354456%' не может.

In вообще в LedgerSMB мы используем оба, в зависимости от того, какой поиск мы делаем. Вы можете увидеть поиск, как:

select * from parts
  WHERE partnumber ilike ?  || '%'
    and plainto_tsquery(get_default_language(), ?) @@ description;

таким образом, они очень разные. Использовать каждый из них там, где это имеет наибольший смысл.