Как против содержит на SQL Server

210

Какой из следующих запросов быстрее (как против содержит)?

SELECT * FROM table WHERE Column LIKE '%test%';

или

SELECT * FROM table WHERE Contains(Column, "test");
user667429
источник
12
Примите ответ, не так ли?
AgentFire
7
Он не был в годах человек.
Крис

Ответы:

174

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

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


CONTAINSЗапрос должен быть:

SELECT * FROM table WHERE CONTAINS(Column, 'test');
Damien_The_Unbeliever
источник
@edze - ты имеешь в виду ту же самую страницу, на которую уже есть ссылки, чтобы быть моим первым упоминанием CONTAINS? Что из этого? Первоначальная форма вопроса не имела Column CONTAIN("%test%",Column)>0ничего общего с действительностью. Это все еще не совсем верно.
Damien_The_Unbeliever
Это помогло нам разобраться с запросом в SharePoint. Есть еще один значок Великого ответа.
ouflak
14

Запустив оба запроса на экземпляре SQL Server 2012, я могу подтвердить, что первый запрос был самым быстрым в моем случае.

Запрос с LIKEключевым словом показал сканирование кластерного индекса.

CONTAINSТакже был кластерный индекс сканирования с дополнительными операторами для полного текста матча и слиянием.

План

МИ С
источник
8
Листовые страницы кластерного индекса представляют собой таблицу. LIKEЗапрос с ведущим шаблоном не сможет эффективно использовать индексную часть. Это нужно будет просто отсканировать все это. Хотя, несомненно, могут быть некоторые обстоятельства, при которых полное сканирование CI работает лучше, чем запрос, использующий полнотекстовый индекс (возможно, если, например, соответствует очень высокий процент строк), это в значительной степени будет исключением, а не каким-то общим правилом, которое вы «можете подтвердить». ».
Мартин Смит
Хорошо, я смотрю на фактический план выполнения, извлекающий более 200 000 записей. Помещая оба запроса в пакет, оба сканировали кластеризованный индекс, но, кроме того, запрос «СОДЕРЖИТ» имеет дополнительную стоимость: ПОЛНОЕ СООТВЕТСТВИЕ ТЕКСТА и СОЕДИНЕНИЕ СЛИЯНИЯ.
MI C
Если он выбирает объединение слиянием, то SQL Server оценивает, что более x% строк в конечном итоге совпадут с предикатом. (Где X = переломный момент ). В таком случае, я полагаю, что оба могут оказаться в равной степени одинаковыми. Затраты, показанные в плане выполнения, являются только оценочными (даже в фактическом плане). Хотя в плане FT есть дополнительные операторы плана выполнения, у него есть некоторые преимущества. Объединение слиянием может прекратиться до конца сканирования, когда у него заканчиваются результаты FT, а также нет необходимости оценивать LIKE.
Мартин Смит
1
Я выполнил аналогичный запрос, чтобы проверить план выполнения в SQL 2012, и он дал мне поиск индекса. Возможно, в приведенном здесь примере таблица была почти пустой. В некоторых случаях SQL использует сканирование индекса в очень маленькой таблице, чтобы использовать индекс, потому что это быстрее.
Хуан
8

Я думаю, что это CONTAINSзаняло больше времени и использовалось, Mergeпотому что в вашем запросе была тире ("-")adventure-works.com .

Тире это слово разрыв, поэтому CONTAINS поиск производился по полнотекстовому индексу, adventureа затем он искал works.comи объединял результаты.

Омри Вальфер
источник
8

Также попробуйте изменить это:

    SELECT * FROM table WHERE Contains(Column, "test") > 0;

К этому:

    SELECT * FROM table WHERE Contains(Column, '"*test*"') > 0;

Первый найдет записи со значениями, такими как « это тест » и « контрольный пример - это план ».

Последний также найдет записи со значениями вроде « я проверяю это » и « это самое большое ».

Джон Доу
источник
4
Работает ли установка звездочки до и после поискового запроса? При чтении документации для CONTAINSнего упоминаются только префиксные термины, такие как «test *», а не суффиксные термины, такие как « test», и не полный поиск по подстроке, например «* test ». Я не пробовал, хотя.
Мэт Форсайт
5
Если вы читаете документацию по CONTAINS ( docs.microsoft.com/en-us/sql/t-sql/queries/… ), поддерживается только поиск префиксов. Я пробовал это экспериментально много раз, и невозможно найти «это самое большое» (в SQL Sever) с Contains (столбец, « тест »)
cl0rkster