Полнотекстовый поиск против 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* - начальная звездочка игнорируется, что немного затрудняет, но тогда индекс состоит из слов, а не символов
Из того, что я знаю о полнотекстовых индексах, я сделаю следующие экстраполяции:
- После индексации он анализирует текст, ищет слова (некоторые РСУБД, например, MySQL, рассматривают слова длиной более 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%" ****