Versión corta: buscar es mucho mejor
Versión menos corta: la búsqueda es generalmente mucho mejor, pero muchas búsquedas (causadas por un mal diseño de consulta con desagradables subconsultas correlacionadas, por ejemplo, o porque está haciendo muchas consultas en una operación de cursor u otro bucle) pueden ser peores que un exploración, especialmente si su consulta puede terminar devolviendo datos de la mayoría de las filas de la tabla afectada.
Ayuda a cubrir a toda la familia para las operaciones de búsqueda de datos para comprender completamente las implicaciones de rendimiento.
Análisis de tabla: sin ningún índice relevante para su consulta, el planificador se ve obligado a utilizar un análisis de tabla, lo que significa que se examinan todas las filas. Esto puede hacer que cada página relacionada con los datos de la tabla se lea desde el disco, que a menudo es el peor de los casos. Tenga en cuenta que para algunas consultas utilizará una exploración de tabla incluso cuando esté presente un índice útil; esto generalmente se debe a que los datos en la tabla son tan pequeños que es más complicado atravesar los índices (si este es el caso, esperaría que planee cambiar a medida que crecen los datos, suponiendo que la medida de selectividad del índice sea buena).
Escaneos de índice con búsquedas de fila: sin encontrar un índice que pueda usarse directamente para una búsqueda, pero un índice que contiene las columnas correctas está presente, se puede usar un escaneo de índice. Por ejemplo, si tiene una tabla grande con 20 columnas con un índice en la columna 1, col2, col3 y emite SELECT col4 FROM exampletable WHERE col2=616
, en este caso col2
es mejor escanear el índice para consultar que escanear toda la tabla. Una vez que se encuentran las filas coincidentes, las páginas de datos deben leerse para recoger col4 para la salida (o unir más), que es lo que es la etapa de "búsqueda de marcadores" cuando la ve en los planes de consulta.
Escaneos de índice sin búsquedas de fila: si el ejemplo anterior fue SELECT col1, col2, col3 FROM exampletable WHERE col2=616
entonces, no es necesario un esfuerzo adicional para leer las páginas de datos: una vez que col2=616
se encuentran las coincidencias de filas de índice, se conocen todos los datos solicitados. Esta es la razón por la que a veces se ven columnas que nunca se buscarán, pero es probable que se soliciten resultados, agregados al final de los índices; puede guardar búsquedas de filas. Al agregar columnas a un índice por este motivo y solo por este motivo, agréguelos con la INCLUDE
cláusula para indicarle al motor que no necesita optimizar el diseño del índice para las consultas basadas en estas columnas (esto puede acelerar las actualizaciones realizadas en esas columnas) . Los escaneos de índice también pueden resultar de consultas sin cláusulas de filtrado: SELECT col2 FROM exampletable
escaneará este índice de ejemplo en lugar de las páginas de la tabla.
Búsqueda de índice (con o sin búsquedas de fila) : en una búsqueda no se considera todo el índice. Para la consulta, SELECT * FROM exampletable WHERE c1 BETWEEN 1234 AND 4567
el motor de consultas puede encontrar la primera fila que coincidirá haciendo una búsqueda basada en un árbol en el índice y c1
luego puede navegar el índice en orden hasta llegar al final del rango (esto es lo mismo con una consulta para c1=1234
ya que podría haber muchas filas que concuerden con la condición incluso para una =
operación). Esto significa que solo deben leerse las páginas de índice relevantes (más algunas necesarias para la búsqueda inicial) en lugar de cada página del índice (o tabla).
Índices agrupados : con un índice agrupado, los datos de la tabla se almacenan en los nodos hoja de ese índice en lugar de estar en una estructura de montón separada. Esto significa que nunca será necesario realizar búsquedas adicionales de filas después de encontrar filas usando ese índice, sin importar qué columnas se necesiten [a menos que tenga datos fuera de la página como TEXT
columnas o VARCHAR(MAX)
columnas que contienen datos largos].
Solo puede tener un índice agrupado por este motivo [1] , el índice agrupado es su tabla en lugar de tener una estructura de montón separada, por lo que si usa uno [2] elija dónde lo coloca cuidadosamente para obtener la máxima ganancia.
También tenga en cuenta que el índice agrupado porque la "clave de agrupación" para la tabla y se incluye en cada índice no agrupado en la tabla, por lo que un índice agrupado amplio generalmente no es una buena idea.
[1] En realidad, puede tener múltiples índices agrupados definiendo índices no agrupados que cubran o incluyan todas las columnas de la tabla, pero es probable que esto sea un desperdicio de espacio tiene un impacto en el rendimiento de escritura, así que si considera hacerlo, asegúrese de Realmente lo necesitas.
[2] Cuando digo "si se utiliza un índice agrupado", tenga en cuenta que en general se recomienda que se haga tener uno en cada mesa. Hay excepciones como con todas las reglas generales, las tablas que ven poco más que inserciones masivas y lecturas no ordenadas (tablas de preparación para procesos ETL tal vez) son el ejemplo de contador más común.
Punto adicional: Escaneos incompletos:
Es importante recordar que, dependiendo del resto de la consulta, una exploración de tabla / índice en realidad no puede explorar toda la tabla; si la lógica lo permite, el plan de consulta puede hacer que se cancele antes. El ejemplo más simple de esto es SELECT TOP(1) * FROM HugeTable
: si mira el plan de consulta para eso, verá que solo se devolvió una fila del escaneo y si observa las estadísticas de E / S ( SET STATISTICS IO ON; SELECT TOP(1) * FROM HugeTable
) verá que solo lee un número muy pequeño de páginas (quizás solo una).
Lo mismo puede suceder si el predicado de una cláusula WHERE
o JOIN ... ON
se puede ejecutar simultáneamente con la exploración que es la fuente de sus datos. La consulta planificador / corredor a veces puede ser muy inteligente acerca de empujar predicados de nuevo hacia las fuentes de datos para permitir la terminación anticipada de las exploraciones de esta manera (y, a veces se puede ser inteligente en la reordenación de las consultas para ayudar a que lo haga!). Si bien los datos fluyen de derecha a izquierda según las flechas en la pantalla del plan de consulta estándar, la lógica se ejecuta de izquierda a derecha y cada paso (de derecha a izquierda) no se ejecuta necesariamente hasta su finalización antes de que pueda comenzar el siguiente. En el ejemplo simple anterior, si observa cada bloque en el plan de consulta como agente, el SELECT
agente le pide al TOP
agente una fila que a su vez le pregunta alTABLE SCAN
agente para uno, luego el SELECT
agente pide otro pero el TOP
agente sabe que no hay necesidad, ni siquiera se molesta en preguntarle al lector de la mesa, el SELECT
agente obtiene una respuesta "no más es relevante" y sabe que todo el trabajo está hecho. Muchas operaciones bloquean este tipo de optimización, por supuesto, tan a menudo en los ejemplos más complicados un recorrido de tabla / índice realmente no leen cada fila, pero tenga cuidado de no sacar la conclusión de que ninguna de exploración debe ser una operación costosa.