Полнотекстовый поиск против LIKE

Мой вопрос об использовании полного текста. Как я знаю, запросы, начинающиеся с%, никогда не используют индекс:

SELECT * from customer where name like %username%

Если я использую полный текст для этого запроса, могу ли я повысить производительность? Может ли SQL Server использовать преимущества полнотекстового индекса для запросов, таких как%username%?

5 ответов

Короткий ответ

В SQL Server нет эффективного способа поиска инфикса, а также LIKE в индексированном столбце или с полнотекстовым индексом.

Длинный ответ

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

Полный текст SQL Server поддерживает подмножество LIKE с префиксным оператором термина. Из документов ( http://msdn.microsoft.com/en-us/library/ms187787.aspx):

SELECT Name
FROM Production.Product
WHERE CONTAINS(Name, ' "Chain*" ');

будет возвращать продукты с именами бензопила, цепная почта и т. д. Функционально, это не дает вам ничего по сравнению со стандартом LIKE оператор (LIKE 'Chain%'), и до тех пор, пока столбец проиндексирован, использование LIKE для поиска с префиксом должно обеспечивать приемлемую производительность.

Оператор LIKE позволяет ставить подстановочный знак где угодно, например LIKE '%chain' и, как вы упомянули, это предотвращает использование индекса. Но с полным текстом звездочка может появляться только в конце условия запроса, так что это вам не поможет.

Используя LIKE, можно выполнять эффективный постфиксный поиск, создав новый столбец, установив его значение в обратном направлении к целевому столбцу и проиндексировав его. Затем вы можете сделать запрос следующим образом:

SELECT Name
FROM Production.Product
WHERE Name_Reversed LIKE 'niahc%'; /* "chain" backwards */

который возвращает товары с их названиями, заканчивающимися на "цепочку".

Я полагаю, вы могли бы затем объединить префикс и взломанный постфиксный хак:

SELECT Name
FROM Production.Product
WHERE Name LIKE 'chain%'
AND Name_Reversed LIKE 'niahc%';

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

Вы должны понимать, как работает индекс. Указатель - это то же самое, что и энциклопедическое издание "Мертвое дерево".

Если вы используете:

SELECT * from customer where name like username%

Индекс в полнотекстовом или без полнотекстового должен работать. но

SELECT * from customer where name like %username%

никогда не будет работать с индексом. и это будет трудоемкий запрос.

Вроде и содержит очень разные -

Принять следующие значения данных

Джон Смит Сэм Смит Джон Фуллер

как 's%' 'Сэм Смит'

как '%s%' 'Джон Смит' 'Сэм Смит'

содержит 's'

содержит "Джон" "Джон Смит" "Джон Фуллер"

содержит 's*' 'Джон Смит' 'Сэм Смит'

содержит s возвращает так же, как содержит s* - начальная звездочка игнорируется, что немного затрудняет, но тогда индекс состоит из слов, а не символов

Из того, что я знаю о полнотекстовых индексах, я сделаю следующие экстраполяции:

  1. После индексации он анализирует текст, ищет слова (некоторые РСУБД, например, MySQL, рассматривают слова длиной более 3 символов) и помещает слова в индекс.
  2. При поиске в полнотекстовом индексе вы ищете слова, которые затем ссылаются на строку.
  3. Если я прав насчет первых двух (для MSSQL), то это будет работать только в том случае, если вы ищете СЛОВА длиной 4 или более символов. Он не найдет "кресло", если вы ищете "кресло".

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

Больше информации:
http://www.developer.com/db/article.php/3446891
http://en.wikipedia.org/wiki/Full_text_search

Вы можете использовать:

SELECT * from customer where CONTAINS(name, 'username')

ИЛИ

SELECT * from customer where FREETEXT(name, 'username')

Mike Chamberlain, вы совершенно правы, поскольку вы предлагаете, что недостаточно что-то искать в " цепочке ", ГДЕ ИМЯ НРАВИТСЯ " цепочка%" И ИМЯ_Реверный НРАВИТСЯ "niahc%" не эквивалентно как "% chain%" ****

Другие вопросы по тегам