LIKE vs CONTAINS en SQL Server

210

¿Cuál de las siguientes consultas es más rápida (LIKE vs CONTAINS)?

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

o

SELECT * FROM table WHERE Contains(Column, "test");
usuario667429
fuente
12
Acepta una respuesta, ¿quieres?
AgentFire
77
No ha estado en años, hombre.
Chris

Respuestas:

174

El segundo (suponiendo que quiere decir CONTAINS, y realmente ponerlo en una consulta válida) debería ser más rápido, ya que puede usar alguna forma de índice (en este caso, un índice de texto completo). Por supuesto, esta forma de consulta solo está disponible si la columna está en un índice de texto completo. Si no es así, solo está disponible el primer formulario.

La primera consulta, usando LIKE, no podrá usar un índice, ya que comienza con un comodín, por lo que siempre requerirá un escaneo completo de la tabla.


La CONTAINSconsulta debe ser:

SELECT * FROM table WHERE CONTAINS(Column, 'test');
Damien_The_Unbeliever
fuente
@edze - quieres decir, ¿la misma página que ya está vinculada para ser mi primera mención CONTAINS? ¿Lo que de ella? La forma original de la pregunta tenía Column CONTAIN("%test%",Column)>0cuál era en ninguna parte cerca de válida. Todavía no está del todo bien.
Damien_The_Unbeliever
Esto nos ayudó a resolver una consulta en SharePoint. Tener otra insignia de Gran Respuesta.
ouflak
14

Después de ejecutar ambas consultas en una instancia de SQL Server 2012, puedo confirmar que la primera consulta fue la más rápida en mi caso.

La consulta con la LIKEpalabra clave mostró un escaneo de índice agrupado.

El CONTAINStambién tuvo un recorrido de índice agrupado con los operadores adicionales para la coincidencia de texto completo y una combinación de mezcla.

Plan

MI C
fuente
8
Las páginas de índice agrupadas son la tabla. Una LIKEconsulta con un comodín inicial no podrá utilizar la parte de índice de manera eficiente. Tendrá que escanear todo. Aunque sin duda puede haber algunas circunstancias en las que el análisis de CI completo funciona mejor que una consulta que utiliza el índice de texto completo (tal vez si una proporción muy alta de filas coincide, por ejemplo), esta será en gran medida la excepción, no una regla general que pueda "confirmar ".
Martin Smith
Bueno, estoy mirando un plan de ejecución real que alcanza más de 200,000 registros. Al poner ambas consultas en un lote, ambas exploraron el índice agrupado, pero además la consulta "CONTAINS" tiene un costo adicional de FULL TEXT MATCH y MERGE JOIN.
MI C
Si elige una combinación de combinación, SQL Server estima que más del x% de las filas terminarán coincidiendo con el predicado. (Donde X = el punto de inflexión ). En ese caso, me imagino que ambos podrían terminar igualados. Los costos que se muestran en el plan de ejecución son solo estimaciones (incluso en el plan real). Si bien hay operadores de planes de ejecución adicionales en el plan FT, tiene algunos beneficios. La combinación de mezcla puede detener antes de que el final de la exploración cuando se queda sin resultados FT y también no tiene que evaluar el LIKE.
Martin Smith
1
He ejecutado una consulta similar para verificar el plan de ejecución en sql 2012 y me dio una búsqueda de índice. Quizás en el ejemplo aquí la mesa estaba casi vacía. En algunos casos, sql usa un escaneo de índice en una tabla muy pequeña para usar el índice porque es más rápido.
Juan
8

Creo que CONTAINStomó más tiempo y se usó Mergeporque tenía un guión ("-") en su consulta adventure-works.com.

El guión es una palabra clave, por lo que CONTAINSbuscó el índice de texto completo adventurey luego buscó works.comy fusionó los resultados.

Omri Valfer
fuente
8

También intente cambiar esto:

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

A esto:

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

El primero encontrará registros con valores como " esto es una prueba " y " un caso de prueba es el plan ".

Este último también encontrará registros con valores como " estoy probando esto " y " este es el mejor ".

John Doe
fuente
44
¿Poner el asterisco antes y después del término de búsqueda funciona? Al leer la documentación CONTAINS, solo menciona el uso de términos de prefijo como 'prueba *', no términos de sufijo como ' prueba' y no búsqueda de subcadena completa como '* prueba '. Sin embargo, no lo he probado.
Matt forsythe
55
Si lee la documentación de CONTAINS ( docs.microsoft.com/en-us/sql/t-sql/queries/… ), solo se admiten búsquedas de prefijos. He intentado esto experimentalmente varias veces y no es posible encontrar "esto es lo mejor" (en SQL Sever) con Contiene (Columna, '" prueba "')
cl0rkster