learn khan how course books beginner academy sql performance equals sql-like

sql - khan - sequel database



Igual(=) vs. LIKE (15)

Cuando se usa SQL, ¿hay alguna ventaja de usar = en una cláusula WHERE lugar de LIKE ?

Sin ningún operador especial, LIKE y = son lo mismo, ¿verdad?


Diferentes operadores

LIKE y = son diferentes operadores. La mayoría de las respuestas aquí se centran en el soporte de comodines, que no es la única diferencia entre estos operadores.

= es un operador de comparación que opera con números y cadenas. Al comparar cadenas, el operador de comparación compara cadenas completas .

LIKE es un operador de cadena que compara carácter por carácter .

Para complicar las cosas, ambos operadores utilizan una collation que puede tener efectos importantes en el resultado de la comparación.

Ejemplo de motivación

Primero identifiquemos un ejemplo donde estos operadores producen resultados obviamente diferentes. Permítame citar del manual de MySQL:

De acuerdo con el estándar SQL, LIKE realiza la comparación por carácter, por lo que puede producir resultados diferentes del operador de comparación =:

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 | +--------------------------------------+

Tenga en cuenta que esta página del manual de MySQL se llama Funciones de comparación de cadenas , y = no se discute, lo que implica que = no es estrictamente una función de comparación de cadenas.

¿Cómo funciona = trabajar?

El estándar SQL § 8.2 describe cómo = compara cadenas:

La comparación de dos cadenas de caracteres se determina de la siguiente manera:

a) Si la longitud en caracteres de X no es igual a la longitud en caracteres de Y, entonces la cadena más corta se reemplaza efectivamente, a efectos de comparación, con una copia de sí misma que se ha extendido a la longitud de la cadena más larga por concatenación a la derecha de uno o más caracteres de relleno, donde el carácter de relleno se elige en función de CS. Si CS tiene el atributo NO PAD, entonces el carácter de relleno es un carácter dependiente de la implementación diferente de cualquier carácter en el conjunto de caracteres de X e Y que clasifica menos que cualquier cadena bajo CS. De lo contrario, el carácter del pad es un.

b) El resultado de la comparación de X e Y viene dado por la secuencia de clasificación CS.

c) Dependiendo de la secuencia de clasificación, dos cadenas pueden compararse como iguales incluso si tienen diferentes longitudes o contienen diferentes secuencias de caracteres. Cuando las operaciones MAX, MIN, DISTINCT, referencias a una columna de agrupación, y los operadores UNION, EXCEPTO e INTERSECT se refieren a cadenas de caracteres, el valor específico seleccionado por estas operaciones de un conjunto de valores iguales depende de la implementación.

(Énfasis añadido.)

¿Qué significa esto? Significa que cuando se comparan cadenas, el operador = es solo una envoltura delgada alrededor de la intercalación actual. Una intercalación es una biblioteca que tiene varias reglas para comparar cadenas. Aquí hay un ejemplo de una compilación binaria de 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); }

Esta recopilación en particular se realiza para comparar byte por byte (por lo que se llama "binario", no da ningún significado especial a las cadenas). Otras colaciones pueden proporcionar comparaciones más avanzadas.

Por ejemplo, aquí hay una clasificación UTF-8 que admite comparaciones que no distinguen entre mayúsculas y minúsculas. El código es demasiado largo para pegarlo aquí, pero vaya a ese enlace y lea el cuerpo de my_strnncollsp_utf8mb4() . Esta intercalación puede procesar múltiples bytes a la vez y puede aplicar varias transformaciones (como una comparación que no distingue entre mayúsculas y minúsculas). El operador = está completamente abstraído de los caprichos de la colación.

¿Cómo funciona el trabajo?

El estándar SQL § 8.5 describe cómo LIKE compara las cadenas:

El <predicado>

M LIKE P

es cierto si existe una partición de M en subcadenas tales que:

i) Una subcadena de M es una secuencia de 0 o más <representaciones de caracteres> contiguas de M y cada <representación de caracteres> de M es parte de exactamente una subcadena.

ii) Si el especificador de la i-ésima subcadena de P es un especificador de caracteres arbitrario, la i-ésima subcadena de M es cualquier <representación de caracteres>.

iii) Si el especificador de la i-ésima subcadena de P es un especificador de cadena arbitrario, entonces la i-ésima subcadena de M es cualquier secuencia de 0 o más <representación de caracteres> s.

iv) Si el especificador de la i-ésima subcadena de P no es ni un especificador de caracteres arbitrario ni un especificador de cadena arbitrario, entonces la i-ésima subcadena de M es igual a ese especificador de la subcadena según la secuencia de clasificación del <predicado similar>, sin la adición de caracteres <space> a M, y tiene la misma longitud que el especificador de subcadena.

v) El número de subcadenas de M es igual al número de especificadores de subcadena de P.

(Énfasis añadido.)

Esto es bastante largo, así que vamos a desglosarlo. Los elementos ii y iii se refieren a los comodines _ y % , respectivamente. Si P no contiene comodines, solo se aplica el artículo iv. Este es el caso de interés planteado por el OP.

En este caso, compara cada "subcadena" (caracteres individuales) en M con cada subcadena en P usando la intercalación actual.

Conclusiones

La línea inferior es que al comparar cadenas, = compara toda la cadena, mientras que LIKE compara un carácter a la vez. Ambas comparaciones utilizan la colación actual. Esta diferencia lleva a resultados diferentes en algunos casos, como se evidencia en el primer ejemplo en esta publicación.

¿Cual deberías usar? Nadie puede decirle que necesita usar el correcto para su caso de uso. No optimice prematuramente cambiando los operadores de comparación.


Además de los comodines, la diferencia entre = AND LIKE dependerá del tipo de servidor SQL y del tipo de columna.

Tomemos este ejemplo:

CREATE TABLE testtable ( varchar_name VARCHAR(10), char_name CHAR(10), val INTEGER ); INSERT INTO testtable(varchar_name, char_name, val) VALUES (''A'', ''A'', 10), (''B'', ''B'', 20); SELECT ''VarChar Eq Without Space'', val FROM testtable WHERE varchar_name=''A'' UNION ALL SELECT ''VarChar Eq With Space'', val FROM testtable WHERE varchar_name=''A '' UNION ALL SELECT ''VarChar Like Without Space'', val FROM testtable WHERE varchar_name LIKE ''A'' UNION ALL SELECT ''VarChar Like Space'', val FROM testtable WHERE varchar_name LIKE ''A '' UNION ALL SELECT ''Char Eq Without Space'', val FROM testtable WHERE char_name=''A'' UNION ALL SELECT ''Char Eq With Space'', val FROM testtable WHERE char_name=''A '' UNION ALL SELECT ''Char Like Without Space'', val FROM testtable WHERE char_name LIKE ''A'' UNION ALL SELECT ''Char Like With Space'', val FROM testtable WHERE char_name LIKE ''A ''

  • Al usar MS SQL Server 2012 , los espacios finales se ignorarán en la comparación, excepto con LIKE cuando el tipo de columna sea VARCHAR .

  • Usando MySQL 5.5 , los espacios finales se ignorarán para = , pero no para LIKE , tanto con CHAR como VARCHAR .

  • Al usar PostgreSQL 9.1 , los espacios son significativos tanto con = como con LIKE utilizando VARCHAR , pero no con CHAR (consulte la documentation ).

    El comportamiento con LIKE también difiere con CHAR .

    Usar los mismos datos que arriba, usar un CAST explícito en el nombre de la columna también hace una diferencia :

    SELECT ''CAST none'', val FROM testtable WHERE char_name LIKE ''A'' UNION ALL SELECT ''CAST both'', val FROM testtable WHERE CAST(char_name AS CHAR) LIKE CAST(''A'' AS CHAR) UNION ALL SELECT ''CAST col'', val FROM testtable WHERE CAST(char_name AS CHAR) LIKE ''A'' UNION ALL SELECT ''CAST value'', val FROM testtable WHERE char_name LIKE CAST(''A'' AS CHAR)

    Esto solo devuelve filas para "CAST ambos" y "CAST col".


Depende del sistema de base de datos.

Generalmente sin caracteres especiales, sí, = y LIKE son los mismos.

Sin embargo, algunos sistemas de bases de datos pueden tratar las configuraciones de intercalación de manera diferente con los diferentes operadores.

Por ejemplo, en MySQL, las comparaciones con = en cadenas siempre distinguen entre mayúsculas y minúsculas por defecto, por lo que LIKE sin caracteres especiales es el mismo. En algunos otros RDBMS, LIKE no distingue entre mayúsculas y minúsculas, mientras que = no lo es.


El operador igual (=) es un "operador de comparación compara dos valores para la igualdad". En otras palabras, en una declaración SQL, no devolverá verdadero a menos que ambos lados de la ecuación sean iguales. Por ejemplo:

SELECT * FROM Store WHERE Quantity = 200;

El operador LIKE "implementa una comparación de coincidencia de patrón" que intenta hacer coincidir "un valor de cadena con una cadena de patrón que contiene caracteres comodín". Por ejemplo:

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

LIKE se usa generalmente solo con cadenas y es igual a (igual que creo) es más rápido. El operador igual trata los caracteres comodín como caracteres literales. La diferencia en los resultados devueltos es la siguiente:

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

Y

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

Devolvería el mismo resultado, aunque usar LIKE generalmente tomaría más tiempo ya que es una coincidencia de patrón. Sin embargo,

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

Y

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

Volvería a obtener resultados diferentes, donde al usar "=" solo se obtendrán resultados con "Chris%" y el operador LIKE devolverá cualquier cosa que comience con "Chris".

Espero que ayude. Una buena información se puede encontrar here .


En Oracle, un "me gusta" sin comodines devolverá el mismo resultado que un "igual", pero podría requerir un procesamiento adicional. De acuerdo con Tom Kyte , Oracle tratará un "me gusta" sin comodines como un "igual" cuando se usan literales, pero no cuando se usan variables de enlace.


Esta es una copia / pegado de otra respuesta mía para la pregunta de SQL ''like'' vs ''='' performance :

Un ejemplo personal utilizando mysql 5.5: Tuve una unión interna entre 2 tablas, una de 3 millones de filas y una de 10 mil filas.

Cuando se utiliza un "me gusta" en un índice como se muestra a continuación (sin comodines), se tardaron unos 30 segundos:

where login like ''12345678''

usando ''explicar'' obtengo:

Cuando se usa un ''='' en la misma consulta, tomó aproximadamente 0.1 segundos:

where login =''12345678''

Usando "explicar" obtengo:

Como puede ver, el like canceló completamente la búsqueda de índice, por lo que la consulta llevó 300 veces más tiempo.


La palabra clave LIKE, sin duda, viene con una "etiqueta de precio de rendimiento" adjunta. Dicho esto, si tiene un campo de entrada que podría incluir caracteres comodín para usar en su consulta, recomendaría usar LIKE solo si la entrada contiene uno de los comodines. De lo contrario, utilice el estándar igual a la comparación.

Atentamente...


Para abordar la pregunta original sobre el rendimiento, todo se reduce a la utilización del índice . Cuando se produce una exploración de tabla simple, "LIKE" y "=" son idénticos . Cuando los índices están involucrados, depende de cómo se forma la cláusula LIKE. Más específicamente, ¿cuál es la ubicación del (los) comodín (es)?

Considera lo siguiente:

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

También puede haber una diferencia insignificante en la creación del plan de consulta cuando se usa "=" vs "LIKE".


Para este ejemplo, damos por sentado que varcharcol no contiene '''' y no tenemos ninguna celda vacía en esta columna

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

El primero da como resultado una salida de 0 filas, mientras que el segundo muestra la lista completa. = es un caso estrictamente coincidente, mientras que like actúa como un filtro. Si el filtro no tiene criterios, todos los datos son válidos.

Me gusta: en virtud de su propósito, funciona un poco más lento y está diseñado para usarse con datos varchar y similares.


Realmente todo se reduce a lo que quiere que haga la consulta. Si te refieres a una coincidencia exacta, entonces usa =. Si te refieres a una coincidencia más difusa, usa LIKE. Decir lo que quieres decir es una buena política con código.


Si busca una coincidencia exacta, puede usar tanto, = como LIKE.

El uso de "=" es un poco más rápido en este caso (en busca de una coincidencia exacta): puede verificar esto usted mismo haciendo la misma consulta dos veces en SQL Server Management Studio, una vez usando "=", una vez usando "LIKE", y luego usando la "Consulta" / "Incluir plan de ejecución real".

Ejecute las dos consultas y debería ver los resultados dos veces, más los dos planes de ejecución reales. En mi caso, se dividieron 50% frente a 50%, pero el "=" plan de ejecución tiene un "costo de subárbol estimado" más pequeño (que se muestra cuando se sitúa sobre la casilla "SELECCIONAR" más a la izquierda), pero nuevamente, es realmente No hay una gran diferencia.

Pero cuando comienzas a buscar con comodines en tu expresión LIKE, el rendimiento de la búsqueda disminuirá. La búsqueda "LIKE Mill%" todavía puede ser bastante rápida: SQL Server puede usar un índice en esa columna, si existe. La búsqueda de "LIKE% expresión%" es terriblemente lenta, ya que la única forma en que SQL Server puede satisfacer esta búsqueda es realizando un análisis completo de la tabla. Así que ten cuidado con tus me gusta!

Bagazo


Una diferencia, aparte de la posibilidad de usar comodines con LIKE, se encuentra en los espacios finales: el operador = ignora el espacio final, pero LIKE no.


Utilizando = evita los caracteres comodín y los conflictos de caracteres especiales en la cadena cuando construye la consulta en tiempo de ejecución.

Esto facilita la vida del programador al no tener que escapar de todos los caracteres comodín especiales que pueden deslizarse en la cláusula LIKE y no producir el resultado deseado. Después de todo, = es el caso de uso del 99%, sería un dolor tener que escapar de ellos cada vez.

rueda los ojos a los 90

También sospecho que es un poco más lento, pero dudo que sea significativo si no hay comodines en el patrón.


= y LIKE no es lo mismo;

  1. = coincide con la cadena exacta
  2. LIKE coincide con una cadena que puede contener comodines (%)

LIKE y = son diferentes. LIKE es lo que utilizarías en una consulta de búsqueda. También permite comodines como _ (comodín de carácter simple) y % (comodín de múltiples caracteres).

= debe usarse si desea coincidencias exactas y será más rápido.

Este sitio explica LIKE