Равно (=) против LIKE - PullRequest
       38

Равно (=) против LIKE

261 голосов
/ 13 февраля 2009

При использовании SQL, есть ли преимущества использования = в предложении WHERE вместо LIKE?

Без каких-либо специальных операторов LIKE и = одинаковы, верно?

Ответы [ 15 ]

236 голосов
/ 25 февраля 2010

Разные операторы

LIKE и = - разные операторы. Большинство ответов здесь сосредоточены на поддержке символов подстановки, что не единственное различие между этими операторами!

= - оператор сравнения, который работает с числами и строками. При сравнении строк оператор сравнения сравнивает целых строк .

LIKE - это строковый оператор, который сравнивает символ за символом .

Чтобы усложнить ситуацию, оба оператора используют сопоставление , которое может оказать существенное влияние на результат сравнения.

Пример мотивации

Давайте сначала определим пример, в котором эти операторы дают явно разные результаты. Позвольте мне процитировать из руководства MySQL:

В соответствии со стандартом SQL, LIKE выполняет сопоставление для каждого символа, поэтому может давать результаты, отличные от оператора сравнения =:

mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
|                                       0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
|                                    1 |
+--------------------------------------+

Обратите внимание, что эта страница руководства MySQL называется Функции сравнения строк , а = не обсуждается, что означает, что = не является строго функцией сравнения строк.

Как работает =? 1037 * Стандарт SQL § 8.2 описывает, как = сравнивает строки: Сравнение двух строк символов определяется следующим образом: a) Если длина в символах X не равна длине в символах Y, то более короткая строка эффективно заменен для сравнения копией сам, который был расширен до длины более длинной строка путем конкатенации справа от одной или нескольких площадок символы, где символ пэда выбирается на основе CS. Если CS имеет атрибут NO PAD, тогда символ пэда является зависящий от реализации символ отличается от любого символ в наборе символов X и Y, который меньше сопоставляется чем любая строка в CS. В противном случае символ пэда является . б) Результат сравнения X и Y дается последовательность упорядочения CS. c) В зависимости от последовательности упорядочения две строки могут сравнить как равные, даже если они имеют разную длину или содержат разные последовательности символов. Когда операции MAX, MIN, DISTINCT, ссылки на столбец группировки и Операторы UNION, EXCEPT и INTERSECT относятся к символам строки, конкретное значение, выбранное этими операциями из набор таких равных значений зависит от реализации. (выделение добавлено). Что это значит? Это означает, что при сравнении строк оператор = является просто тонкой оболочкой для текущего сопоставления. Сличение - это библиотека, которая имеет различные правила для сравнения строк. Вот пример двоичного сопоставления из MySQL : static int my_strnncoll_binary(const CHARSET_INFO *cs __attribute__((unused)), const uchar *s, size_t slen, const uchar *t, size_t tlen, my_bool t_is_prefix) { size_t len= MY_MIN(slen,tlen); int cmp= memcmp(s,t,len); return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen); } Это конкретное сопоставление происходит для сравнения побайтно (именно поэтому оно называется "двоичным" - оно не придает никакого особого значения строкам). Другие сопоставления могут обеспечить более сложные сравнения. Например, вот сопоставление UTF-8 , которое поддерживает сравнения без учета регистра. Код слишком длинный для вставки, но перейдите по этой ссылке и прочитайте текст my_strnncollsp_utf8mb4(). Такое сопоставление может обрабатывать несколько байтов одновременно и может применять различные преобразования (например, сравнение без учета регистра). Оператор = полностью абстрагируется от капризов сопоставления. Как работает LIKE? 1073 * Стандарт SQL § 8.5 описывает, как LIKE сравнивает строки: M LIKE P верно, если существует разбиение M на подстроки такой что: i) Подстрока M представляет собой последовательность из 0 или более смежных <символьное представление> s M и каждый <символ представление> M является частью ровно одной подстроки. ii) Если i-й подстрока спецификатора P является произвольной спецификатор символа, i-я подстрока M является любой единственной <символьное представление>. iii) Если i-й подстрока спецификатора P является произвольной строкой спецификатор, то i-я подстрока M является любой последовательностью 0 или более <символьное представление> s. iv) Если i-й подстрока спецификатора P не является спецификатор произвольного символа или спецификатор произвольной строки, тогда i-я подстрока M равна этой подстроке спецификатор в соответствии с последовательностью сортировки <как предикат>, без добавления символов в M и имеет ту же длину, что и подстрока Спецификатор. v) Количество подстрок M равно количеству подстрока спецификаторов P. (выделение добавлено.) Это довольно многословно, так что давайте разберемся. Пункты ii и iii относятся к групповым символам _ и % соответственно. Если P не содержит подстановочных знаков, применяется только пункт iv. Это тот случай, который представляет интерес для ФП. В этом случае он сравнивает каждую «подстроку» (отдельные символы) в M с каждой подстрокой в ​​P с использованием текущего сопоставления. Выводы

Суть в том, что при сравнении строк = сравнивает всю строку, тогда как LIKE сравнивает один символ за раз. Оба сравнения используют текущее сопоставление. Это различие приводит к разным результатам в некоторых случаях, о чем свидетельствует первый пример в этом посте.

Какой из них вы должны использовать? Никто не может сказать вам это - вам нужно использовать тот, который подходит для вашего случая использования. Не оптимизируйте преждевременно, переключая операторы сравнения.

167 голосов
/ 13 февраля 2009

Оператор equals (=) представляет собой «оператор сравнения сравнивает два значения на равенство». Другими словами, в операторе SQL он не вернет true, если обе стороны уравнения не равны. Например:

SELECT * FROM Store WHERE Quantity = 200;

Оператор LIKE "реализует сравнение сопоставления с образцом", который пытается сопоставить "строковое значение со строкой с образцом, содержащей символы подстановки" Например:

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

LIKE обычно используется только со строками и равно (я считаю) быстрее. Оператор equals обрабатывает символы подстановки как буквенные символы. Разница в результатах возвращается следующим образом:

SELECT * FROM Employees WHERE Name = 'Chris';

И

SELECT * FROM Employees WHERE Name LIKE 'Chris';

Возвращает тот же результат, хотя использование LIKE, как правило, занимает больше времени, чем сопоставление с шаблоном. Тем не менее,

SELECT * FROM Employees WHERE Name = 'Chris%';

И

SELECT * FROM Employees WHERE Name LIKE 'Chris%';

Возвращает другие результаты, при этом использование «=» приводит только к результатам с возвращением «Chris%», а оператор LIKE возвращает все, начиная с «Chris».

Надеюсь, это поможет. Немного полезной информации можно найти здесь .

16 голосов
/ 13 февраля 2009

LIKE и = различны. LIKE - это то, что вы будете использовать в поисковом запросе. Также допускаются подстановочные знаки, такие как _ (подстановочный знак простого символа) и % (подстановочный знак из нескольких символов).

= следует использовать, если вам нужны точные совпадения, и это будет быстрее.

Этот сайт объясняет LIKE

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

Это копия / вставка другого моего ответа на вопрос SQL 'like' vs '=' performance :

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

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

where login like '12345678'

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

enter image description here

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

where login ='12345678'

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

enter image description here

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

11 голосов
/ 13 февраля 2009

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

10 голосов
/ 13 февраля 2009

Зависит от системы баз данных.

Обычно без специальных символов, да, = и LIKE одинаковы.

Однако некоторые системы баз данных могут по-разному обрабатывать параметры сортировки для разных операторов.

Например, в MySQL сравнения со строками = on по умолчанию всегда регистрозависимы, поэтому LIKE без специальных символов одинаков. В некоторых других СУБД LIKE нечувствителен к регистру, а = нет.

9 голосов
/ 14 ноября 2012

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

select * from some_table where varcharCol = ''
select * from some_table where varcharCol like ''

Первое приводит к выводу 0 строк, а второе показывает весь список. = строго совпадает с регистром, в то время как похоже действует как фильтр. если фильтр не имеет критериев, все данные действительны.

like - в силу своего назначения работает немного медленнее и предназначено для использования с varchar и аналогичными данными.

6 голосов
/ 13 апреля 2010

Чтобы ответить на первоначальный вопрос о производительности, сводится к использованию индекса . Когда происходит простое сканирование таблицы, "LIKE" и "=" идентичны . Когда задействованы индексы, зависит от того, как сформировано предложение LIKE. Более конкретно, каково расположение подстановочных знаков?


Рассмотрим следующее:

CREATE TABLE test(
    txt_col  varchar(10) NOT NULL
)
go

insert test (txt_col)
select CONVERT(varchar(10), row_number() over (order by (select 1))) r
  from master..spt_values a, master..spt_values b
go

CREATE INDEX IX_test_data 
    ON test (txt_col);
go 

--Turn on Show Execution Plan
set statistics io on

--A LIKE Clause with a wildcard at the beginning
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '%10000'
--Results in
--Table 'test'. Scan count 3, logical reads 15404, physical reads 2, read-ahead reads 15416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index SCAN is 85% of Query Cost

--A LIKE Clause with a wildcard in the middle
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '1%99'
--Results in
--Table 'test'. Scan count 1, logical reads 3023, physical reads 3, read-ahead reads 3018, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost for test data, but it may result in a Table Scan depending on table size/structure

--A LIKE Clause with no wildcards
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO

--an "=" clause = does Index Seek same as above
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col = '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO


DROP TABLE test

При создании "=" и "LIKE" может также быть незначительная разница в создании плана запроса.

6 голосов
/ 13 февраля 2009

Если вы ищете точное совпадение, вы можете использовать оба, = и LIKE.

Использование "=" в этом случае немного быстрее (поиск точного соответствия) - вы можете проверить это самостоятельно, дважды выполнив один и тот же запрос в SQL Server Management Studio, один раз используя "=", один раз используя "LIKE". », а затем с помощью« Запрос »/« Включить фактический план выполнения ».

Выполните два запроса, и вы должны увидеть результаты дважды, а также два фактических плана выполнения. В моем случае они были разделены на 50% против 50%, но план выполнения «=» имеет меньшую «оценочную стоимость поддерева» (отображается при наведении курсора на крайнее левое поле «ВЫБОР»), но опять же, это действительно не большая разница.

Но когда вы начнете поиск с подстановочными знаками в выражении LIKE, эффективность поиска снизится. Поиск "LIKE Mill%" все еще может быть довольно быстрым - SQL Server может использовать индекс для этого столбца, если он есть. Поиск "LIKE% expression%" ужасно медленный, поскольку единственный способ, которым SQL Server может удовлетворить этот поиск, - выполнить полное сканирование таблицы. Так что будьте осторожны с вашими как!

Марк

6 голосов
/ 13 февраля 2009

Использование = позволяет избежать конфликтов символов подстановки и специальных символов в строке при построении запроса во время выполнения.

Это облегчает жизнь программиста, так как не требуется экранировать все специальные символы подстановки, которые могут появиться в предложении LIKE, и не дает ожидаемого результата. В конце концов, = 99% сценария использования, было бы больно каждый раз избегать их.

закатывает глаза в 90-х

Я также подозреваю, что это немного медленнее, но я сомневаюсь, что это важно, если в шаблоне нет подстановочных знаков.

...