Para poder entender lo que hace de SQL Server antes de aplicar cualquier tipo de índice en una consulta tenemos que entender que el SQL Server tiene que determinar si un determinado índice es útil o no. Este articulo trata de mostrar como un predicado mal escrito impide el uso de accesos puntuales mediante INDEX SEEK.
Para entender esto vamos a simplificar las cosas y comenzar con una consulta trivial.
SELECT <Columnas devueltas>
FROM <Tabla>
WHERE <Condición>
Está simple consulta, que utiliza una sola tabla, precisa de las “columnas devueltas” y de las columnas utilizadas en la condición para verificar si la cumplen. Por el momento consideraremos condiciones simples sin subconsultas.
El punto crítico aquí es la condición, ya que es esta la que limita la cantidad de filas devueltas y por lo tanto la posibilidad de hacer un acceso puntual (SEEK) mediante índices o una exploración (SCAN) ya sea de índices o de tabla dependiendo de las columnas involucradas. El problema radica en que el SQL Server debe determinar conociendo información estadística de los datos de las columnas involucradas en la condición, la estructura de los índices disponibles y la forma en que está escrita la condición si el uso de un índice mediante acceso puntual (SEEK) es adecuado o es preferible una exploración (SCAN).
Vamos a ignorar por el momento las columnas devueltas y el tipo de índice (que dejaremos para otros artículos ) a efectos de simplificar el análisis y entender la idea de los argumentos de búsqueda,. Simplemente nos vamos a concentrar en como un predicado de búsqueda mal expresado puede impedir el uso de los índices mediante un SEEK.
Veamos un ejemplo usando AdventureWorks:
USE AdventureWorks
GO
SELECT *
FROM Sales.SalesOrderHeader
WHERE customerid = 117
Aquí vemos como el predicado de búsqueda permite determinar facilmente que el acceso puntual por índice es útil. Puede verse el Index Seek. Esto ocurre porque el predicado customerid = 117 es un buen argumento de búsqueda y por lo tanto dado que tiene información estadística puede determinar que le conviene usar el índice porque determina que devuelve un porcentaje muy bajo de filas en proporción a las que tiene la tabla.
Qué ocurre si cambiamos el argumento de búsqueda:
SELECT *
FROM Sales.SalesOrderHeader
WHERE customerid + 1 = 118
En este caso el resultado es el mismo, en cuanto a filas devueltas, ya que ambos predicados son equivalentes, pero la condición customerid + 1 = 118 no permite el acceso puntual mediante SEEK y debe hacer un INDEX SCAN.
Si analizamos un poco ambas condiciones vemos que la segunda condición por igualdad esta aplicada al resultado de una operación suma y no a una columna por lo que no le es posible al motor del SQL Server hacer una búsqueda puntual porque lo que está en el índice no es el resultado de la suma sino el customerid. Por lo tanto no le queda más remedio que revisar fila por fila para determinar si se cumple la condición de igualdad.
Para verlo más claramente es muy parecido a si buscamos a todas las Daniela de la guía telefónica. Dado que esta ordenada por apellido y luego por nombre no es posible hacer un acceso puntual a las páginas donde se encuentran y es necesario revisar todas las páginas de la guía verificando abonado telefónico por abonado telefónico si se cumple la condición. Esto mismo ocurriría aunque hubiera solo 10 personas con nombre Daniela.
Conclusión
Si no escribimos las condiciones de nuestras consultas de manera adecuada nunca podrá usar los índices para realizar accesos puntuales (INDEX SEEK). En líneas generales las condiciones requieren de un predicado del tipo columna <operador> <expresión>, donde no todos los operadores cumplen con esta condición.