SQL 'как' vs '=' производительность - PullRequest
69 голосов
/ 26 мая 2011

Этот вопрос обходит то, что мне интересно, но ответы не совсем решают его.

Казалось бы, в общем случае '=' быстрее, чем 'like' при использовании подстановочных знаков.Это кажется общепринятой мудростью.Однако предположим, что у меня есть столбец, содержащий ограниченное количество различных фиксированных, жестко закодированных идентификаторов varchar, и я хочу выбрать все строки, соответствующие одному из них:

select * from table where value like 'abc%'

и

select * from table where value = 'abcdefghijklmn'

«Like» нужно только проверить первые три символа, чтобы найти совпадение, тогда как «=» должен сравнить всю строку.В этом случае мне кажется, что «подобное» будет иметь преимущество при прочих равных условиях.

Это задумано как общий, академический вопрос, и поэтому не должно иметь значения, какая БД, но возниклас использованием SQL Server 2005.

Ответы [ 8 ]

54 голосов
/ 26 мая 2011

См. http://myitforum.com/cs2/blogs/jnelson/archive/2007/11/16/108354.aspx

Цитата оттуда:

правила использования индекса в LIKE примерно такие:

  • Если ваш критерий фильтрации использует equals =, а поле проиндексировано, то, скорее всего, он будет использовать INDEX / CLUSTERED INDEX SEEK

  • Если критерии вашего фильтра используют LIKE без подстановочных знаков (например, еслиу вас в веб-отчете есть параметр, который МОЖЕТ иметь%, но вместо этого вы используете полную строку), вероятность того, что индекс будет использовать индекс # 1, также высока.Увеличенная стоимость - почти ничто.

  • Если в критериях фильтра используется LIKE, но с подстановочным знаком в начале (как в Name0 LIKE '% UTER'), гораздо реже использоватьиндекс, но он все равно может, по крайней мере, выполнить INDEX SCAN по полному или частичному диапазону индекса.

  • ОДНАКО, если ваш критерий фильтра использует LIKE, но начинается с STRING FIRST игде-то подстановочные знаки после этого (как в Name0 LIKE 'COMP% ER'), тогда SQL может просто использовать INDEX SEEK для быстрого поиска строк, которые имеют одинаковые первые начальные символы, а затем просматривать эти строки на предмет точного соответствия.

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

36 голосов
/ 26 мая 2011

Это измеримая разница.

Запустите следующее:

Create Table #TempTester (id int, col1 varchar(20), value varchar(20))
go

INSERT INTO #TempTester (id, col1, value)
VALUES
(1, 'this is #1', 'abcdefghij')
GO

INSERT INTO #TempTester (id, col1, value)
VALUES
(2, 'this is #2', 'foob'),
(3, 'this is #3', 'abdefghic'),
(4, 'this is #4', 'other'),
(5, 'this is #5', 'zyx'),
(6, 'this is #6', 'zyx'),
(7, 'this is #7', 'zyx'),
(8, 'this is #8', 'klm'),
(9, 'this is #9', 'klm'),
(10, 'this is #10', 'zyx')
GO 10000

CREATE CLUSTERED INDEX ixId ON #TempTester(id)CREATE CLUSTERED INDEX ixId ON #TempTester(id)

CREATE NONCLUSTERED INDEX ixTesting ON #TempTester(value)

Тогда:

SET SHOWPLAN_XML ON

Тогда:

SELECT * FROM #TempTester WHERE value LIKE 'abc%'

SELECT * FROM #TempTester WHERE value = 'abcdefghij'

Полученный план выполнения показывает, что стоимость первой операции (LIKE) примерно в 10 раз дороже, чем =.

Если вы можете использовать = сравнение, сделайте это.

13 голосов
/ 26 мая 2011

Также следует помнить, что при использовании like некоторые разновидности sql игнорируют индексы, что снижает производительность.Это особенно верно, если вы не используете шаблон «начинается с», как в вашем примере.

Вам действительно нужно посмотреть на план выполнения запроса и посмотреть, что он делает, угадайте как можно меньше.

При этом шаблон «начинается с» может и оптимизируется на сервере sql.Он будет использовать индекс таблицы.По этой причине EF 4.0 переключился на like для StartsWith.

7 голосов
/ 26 мая 2011

Если value неиндексирован, оба результата приводят к сканированию таблицы.Разница в производительности в этом сценарии будет незначительной.

Если индексировано value, как указывает Даниэль в своем комментарии, = приведет к поиску индекса, который будет O (log N) производительности.LIKE (скорее всего - в зависимости от того, насколько он избирателен) приведет к частичному сканированию индекса >= 'abc' и < 'abd', что потребует больше усилий, чем =.

Обратите внимание, что я 'Я говорю о SQL Server здесь - не все СУБД будут хороши с LIKE.

5 голосов
/ 27 мая 2011

Вы задаете не тот вопрос.В базах данных не важна производительность оператора, всегда SARGability выражения и совместимость всего запроса.Производительность самого оператора в значительной степени не имеет значения.

Итак, как же LIKE и = сравниваются с точки зрения SARGability?LIKE, когда используется с выражением, которое не начинается с константы (например, когда используется LIKE '%something'), по определению не SARGabale.Но делает ли это = или LIKE 'something%' SARGable?Нет. Как и в случае любого вопроса о производительности SQL, ответ не лежит на запросе текста, а на развернутой схеме.Эти выражения могут быть SARGable , если существует индекс для их удовлетворения.

Итак, по правде говоря, между = и LIKE есть небольшие различия.Но спрашивать, является ли один оператор или другой оператор «быстрее» в SQL, все равно, что спрашивать: «Что быстрее, красная машина или синяя машина?».Вам следует задавать вопросы о размере двигателя и весе транспортного средства, а не о цвете ... Чтобы подойти к вопросам об оптимизации реляционных таблиц, вам нужно поискать индексы и выражения в предложении WHERE (и других предложениях, но обычно начинается с WHERE).

4 голосов
/ 19 февраля 2015

Личный пример использования mysql 5.5: у меня было внутреннее соединение между 2 таблицами, одной из 3 миллионов строк и одной из 10 тысяч строк.

При использовании аналогичного индекса, как показано ниже (без подстановочных знаков), это заняло около 30 секунд:

where login like '12345678'

используя 'объяснение' я получаю:

enter image description here

При использовании '=' в том же запросе это заняло около 0,1 секунды:

where login ='600009'

Используя 'объяснение', я получаю:

enter image description here

Как видите, like полностью отменил поиск по индексу, поэтому запрос занял в 300 раз больше времени.

0 голосов
/ 06 ноября 2016

Может быть, вы ищете Полнотекстовый поиск .

В отличие от полнотекстового поиска, предикат LIKE Transact-SQL работает на только персонажи Кроме того, вы не можете использовать предикат LIKE для запрос отформатированных двоичных данных. Кроме того, LIKE-запрос к большому объем неструктурированных текстовых данных намного медленнее, чем эквивалент полнотекстовый запрос к тем же данным . Как запрос против миллионов из строк текстовых данных может потребоваться минуты для возврата; тогда как полный текст запрос может занять всего несколько секунд или меньше для тех же данных, в зависимости на количество возвращаемых строк.

0 голосов
/ 04 августа 2015

Перво-наперво,

они не всегда равны

    select 'Hello' from dual where 'Hello  ' like 'Hello';

    select 'Hello' from dual where 'Hello  ' =  'Hello';

, когда вещи не всегда равны, говорить об их производительности не так уж важно.

Если вы работаете со строками и только с переменными char, тогда вы можете говорить о производительности.Но не используйте like и "=" как взаимозаменяемые.

Как вы видели во многих постах (выше и в других вопросах), в случаях, когда они равны, производительность like замедляется из-за сопоставления с шаблоном (collation)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...