Полнотекстовый поиск против НРАВИТСЯ

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

SELECT * from customer where name like %username%

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


person profvm    schedule 16.11.2010    source источник


Ответы (6)


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

Не существует эффективного способа выполнения поиска по инфиксу в 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, можно выполнять эффективный поиск postfix, создавая новый столбец, устанавливая его значение в обратное значение целевого столбца и индексируя его. Затем вы можете запросить следующим образом:

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%';

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

person Mike Chamberlain    schedule 01.12.2010
comment
Очень креативная идея по комбинированию префикса и обратного постфикса! Никогда бы не подумал об этом! - person RSW; 26.01.2013
comment
Это все еще относится к SQL Server 2012 и 2014? знак равно - person jpmc26; 22.10.2015
comment
Таким образом, вы говорите в случае, когда у вас было что-то вроде: Выберите * Из людей, где полное имя, например «%john%». Было бы более эффективно сделать что-то вроде этого: Выберите * Из людей, где имя, например «john%» или Фамилия например, «Джон%». Имеет ли это смысл? - person Jonathan; 04.11.2016
comment
Потенциально да, если проиндексированы и имя, и фамилия. Однако запросы не совсем эквивалентны, так как второй запрос не найдет человека с фамилией Литтлджон. - person Mike Chamberlain; 04.11.2016

Вы должны понимать, как работает index. Указатель такой же, как сухостойное издание энциклопедии.

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

SELECT * from customer where name like username%

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

SELECT * from customer where name like %username%

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

person Ran Bar-Zik    schedule 16.11.2010
comment
Хорошо, Ран, большое спасибо за ваш комментарий. Я согласен с вами в отношении рабочего механизма для индекса (например, энциклопедия). Но полный текст намного быстрее (1/20), чем аналогичный запрос для нашей ситуации (ВЫБЕРИТЕ * от клиента, где имя, например, %username %). На самом деле мне интересно, как это достигается? - person profvm; 16.11.2010
comment
developer.com/db/article.php/3446891 LIKE полностью отличается от полнотекстовый поиск. В вашем первом запросе будет работать только простой индекс атрибута char/varchar. Полнотекстовый индекс в этом случае не используется. - person AlexanderMP; 17.11.2010

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

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

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

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

person AlexanderMP    schedule 16.11.2010

Нравится и содержит очень разные -

Возьмите следующие значения данных

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

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

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

содержит "с"

содержит 'джон' 'джон смит' 'джон фуллер'

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

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

person Ed Green    schedule 05.05.2016

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

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

OR

SELECT * from customer where FREETEXT(name, 'username')
person Rafiqul Islam    schedule 22.06.2019

https://stackoverflow.com/users/289319/mike-chamberlain, вы совершенно правы, поскольку предполагаете, что это недостаточно для поиска чего-либо 'chain', ГДЕ Name LIKE 'chain%' AND Name_Reversed LIKE 'niahc%' не эквивалентно like'% цепь%'****

person Michel    schedule 19.05.2017