post icon

Optimizar las querys con cláusula LIKE en SQL [SQL-Tunning]

Continuando con los tips para optimizar nuestras querys SQL, trataremos unas de las clásulas que más ralentizan éstas. El operador LIKE.

La definición que exponen en la TechNet me gusta y dice asi:

Determina si una cadena de caracteres específica coincide con un patrón especificado. Un patrón puede contener caracteres normales y caracteres comodín. Durante la operación de búsqueda de coincidencias de patrón, los caracteres normales deben coincidir exactamente con los caracteres especificados en la cadena de caracteres. Sin embargo, los caracteres comodín pueden coincidir con fragmentos arbitrarios de la cadena. La utilización de caracteres comodín hace que el operador LIKE sea más flexible que los operadores de comparación de cadenas = y !=.

Como se tiene que trabajar con cadenas de texto, dentro de otras cadenas más grandes normalmente, es un proceso lento para la comparación. Muchas veces escuche “por los pasillos” a gente decir que si usas LIKE olvidate del uso del índice. Esto es totalmente falso (siempre y cuando el campo tenga un índice), siempre los utiliza, pero si no sabemos optimizar en vez de hacer un uso efectivo estaríamos realizando un Index Scan.

Si bien existen varios argumentos que podemos agregar al LIKE, el más común y pesado es el comodín (%). Este “problema“, si se lo puede llamar así ocurren en SQL Server, Oracle, Postgre y MySQL (probablemente en otros motores también, pero no me constan) así como la solución que veremos aplica a todos ellos. Si requieren comprender el plan de ejecución pueden leerlo aquí.

Hagamos 3 pruebas y veamos sus planes de ejecución (el SHOWPLAN sólo lo haremos en SQL Server pero si prueban verán que es igual en los otros tres mencionados anteriormente)

select c.NumDocu from clientes c where c.NumDocu like '%377'; 

select c.NumDocu from clientes c where c.NumDocu like '%377%';


select c.NumDocu from clientes c where c.NumDocu like '377%';

Si se fijan bien, el lugar donde aparece el comodín en cada query es distinto y en los 2 primeros casos el motor barre completamente el índice con un Index Scan, lo que lleva más tiempo terminar de ejecutarlo y el tercer ejemplo hace una búsqueda en el índice con Index Seek.

Lamentablemente no podemos optimizar la segunda query y estamos obligados a realizar el barrido completo, pero con el primer ejemplo tenemos una solución sencilla pero que hace la diferencia realmente. La misma consta en crear un nuevo campo en la tabla llamado “NumDocu_Reverse” con el mismo tipo de dato y longitud que el campo NumDocu agregándole a su vez un índice Non-Clustered (no olviden esto), y lo poblamos con los datos del campo original pero en “reversado”, con un trigger podrían solucionarlo.

update Cliente set NumDocu_Reverse = REVERSE(NumDocu) from Cliente;

Luego omitimos la primer consulta y usamos su reverso asi:

select NumDocu_Reverse from clientes c where c.NumDocu_Reverse like '773%';

Listo, ya estarán usando el índice como debe ser..

 

Comentarios desde Facebook:

Sin Comentarios aun, puedes tú ser el primero en comentar!

Deja tu Comentario

Responder