LIKE vs CONTAINS на SQL Server


210

Який із наступних запитів швидше (LIKE vs CONTAINS)?

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

або

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

12
Прийміть відповідь, чи не так?
AgentFire

7
Він не був у літній людині.
Кріс

Відповіді:


174

Другий (якщо припустити, що ви маєте на увазі CONTAINS, і насправді помістити його у дійсний запит), повинен бути швидшим, тому що він може використовувати певну форму індексу (у цьому випадку повнотекстовий індекс). Звичайно, ця форма запиту доступна лише в тому випадку, якщо стовпець знаходиться в повнотекстовому покажчику. Якщо ні, то доступна лише перша форма.

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


CONTAINSЗапит повинен бути:

SELECT * FROM table WHERE CONTAINS(Column, 'test');

@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) з "Містить" (стовпець, " тест ")
cl0rkster
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.