Al observar un plan de ejecución de una consulta de ejecución lenta, noté que algunos de los nodos son búsqueda de índice y algunos de ellos son exploración de índice.
¿Cuál es la diferencia entre una búsqueda de índice y una exploración de índice?
¿Cuál funciona mejor?
¿Cómo elige SQL uno sobre el otro?
Me doy cuenta de que son 3 preguntas, pero creo que responder la primera explicará las otras.
Respuestas:
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 casocol2
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 quecol2=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 laINCLUDE
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 yc1
luego puede navegar el índice en orden hasta llegar al final del rango (esto es lo mismo con una consulta parac1=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 oVARCHAR(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
oJOIN ... 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, elSELECT
agente le pide alTOP
agente una fila que a su vez le pregunta alTABLE SCAN
agente para uno, luego elSELECT
agente pide otro pero elTOP
agente sabe que no hay necesidad, ni siquiera se molesta en preguntarle al lector de la mesa, elSELECT
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.fuente
En general, las búsquedas son buenas, los escaneos son malos.
Las búsquedas son donde la consulta puede hacer un uso efectivo del índice y usarlo para encontrar las filas que necesita.
Los escaneos son donde la consulta busca a través de todo el índice tratando de encontrar lo que necesita.
¿Cómo elige SQL? En lo más profundo del optimizador de consultas, la decisión se toma en función de su consulta y los índices disponibles y la información estadística asociada con esos índices.
Hay algunos libros para leer que pueden ser de interés aquí. Ambos de la librería Red-Gate en http://www.red-gate.com/community/books/
fuente
Si desea profundizar en el tema, un libro muy útil (al menos para mí) es Planes de ejecución de SQL Server de Grant Fritchey, disponible gratuitamente en RedGate aquí .
Si tiene una consulta como
SQL Server probablemente usará un escaneo de índice, ya que necesita recorrer todas las filas para mostrar los resultados requeridos.
De lo contrario,
sin duda resultará en una búsqueda de índice. SQL Server utilizará la estructura del árbol B del índice myID y la recuperación de la línea adecuada será mucho más rápida.
fuente
Otros han definido suficientemente bien las diferencias entre búsqueda y exploración. En este caso, su consulta y el planificador de ejecución deberían proporcionarle la información que necesita para ver qué valores se utilizan como predicados (filtros) para la consulta en cada parte. Por lo general, es una buena práctica agregar siempre índices no agrupados en claves externas, y dependiendo de los casos de uso en el código del programa, es posible que desee considerar la creación de índices de columnas múltiples adicionales o índices de columnas incluidos también. Con la terminología presentada aquí, una búsqueda en Google dará resultados decentes en ejemplos de cada uno.
Pero, como ejemplo, supongamos que su código está buscando Columna A y Columna B en filtros dados, pero también desea devolver los valores de Columna C y Columna E, es posible que desee crear un índice en la Columna A y B con INCLUIR opción que contiene las columnas C y E. De esa manera, una búsqueda de índice única devolverá todo lo que necesita, ya que no es necesario realizar una búsqueda para recuperar los otros valores (C y E) en la misma fila.
fuente