Mientras estudiaba para el examen 70-433, noté que puede crear un índice de cobertura de una de las dos formas siguientes.
CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)
- O -
CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)
La cláusula INCLUDE es nueva para mí. ¿Por qué lo usaría y qué pautas sugeriría para determinar si crear un índice de cobertura con o sin la cláusula INCLUDE?
SELECT
y para algunos no \?Usaría INCLUDE para agregar una o más columnas al nivel de hoja de un índice no agrupado, si al hacerlo, puede "cubrir" sus consultas.
Imagine que necesita consultar la identificación de un empleado, la identificación del departamento y el apellido.
Si tiene un índice no agrupado en (Id. De empleado, Id. De departamento), una vez que encuentre a los empleados de un departamento determinado, ahora tiene que hacer una "búsqueda de marcadores" para obtener el registro completo de los empleados, solo para obtener la columna de apellido . Eso puede ser bastante costoso en términos de rendimiento, si encuentra muchos empleados.
Si ha incluido ese apellido en su índice:
entonces toda la información que necesita está disponible en el nivel de hoja del índice no agrupado. Simplemente buscando en el índice no agrupado y encontrando a sus empleados para un departamento determinado, tiene toda la información necesaria, y la búsqueda de marcadores para cada empleado encontrado en el índice ya no es necesaria -> ahorra mucho tiempo.
Obviamente, no puede incluir todas las columnas en cada índice no agrupado, pero si tiene consultas que faltan solo una o dos columnas para "cubrir" (y que se usan mucho), puede ser muy útil INCLUIR esas en un índice no agrupado adecuado.
fuente
JOIN
claves en la consulta, y lasINCLUDE
s deben ser los datos que está recuperando pero no ordenando.Esta discusión se está perdiendo en el punto importante: la pregunta no es si las "columnas sin clave" son mejores para incluir como columnas de índice o como columnas incluidas .
La pregunta es ¿qué tan costoso es usar el mecanismo de inclusión para incluir columnas que realmente no son necesarias en el índice ? (normalmente no forma parte de las cláusulas where, pero a menudo se incluye en las selecciones). Entonces tu dilema es siempre:
Donde: id1, id2 ... idN son columnas que se usan a menudo en restricciones y col1, col2 ... colN son columnas que se seleccionan a menudo, pero generalmente no se usan en restricciones
(La opción de incluir todas estas columnas como parte de la clave de índice siempre es una tontería (a menos que también se usen en restricciones), porque siempre sería más costoso de mantener ya que el índice debe actualizarse y ordenarse incluso cuando "llaves" no han cambiado).
¿Entonces usa la opción 1 o 2?
Respuesta: Si su tabla rara vez se actualiza, en su mayoría se inserta o se elimina, entonces es relativamente económico usar el mecanismo de inclusión para incluir algunas "columnas activas" (que a menudo se usan en selecciones, pero no se usan a menudo en restricciones) ya que las inserciones / eliminaciones requieren que el índice se actualice / clasifique de todos modos y, por lo tanto, se asocia una pequeña sobrecarga adicional con el almacenamiento de algunas columnas adicionales mientras ya se actualiza el índice. La sobrecarga es la memoria adicional y la CPU utilizada para almacenar información redundante en el índice.
Si las columnas que considera agregar como columnas incluidas a menudo se actualizan (sin que se actualicen las columnas de clave de índice) o , si son tantas que el índice se acerca a una copia de su tabla, use la opción 1 Sugeriría! Además, si agregar ciertas columnas de inclusión no hace ninguna diferencia de rendimiento, es posible que desee omitir la idea de agregarlas :) ¡Verifique que sean útiles!
El número promedio de filas por los mismos valores en las claves (id1, id2 ... idN) también puede ser de cierta importancia.
Tenga en cuenta que si se usa una columna, que se agrega como una columna de índice incluida, en la restricción : siempre que se pueda usar el índice como tal (en función de la restricción contra las columnas de clave de índice), entonces SQL Server coincide la restricción de columna contra el índice (valores de nodo de hoja) en lugar de ir de la manera costosa alrededor de la tabla misma.
fuente
Las columnas de índice básicas están ordenadas, pero las columnas incluidas no están ordenadas. Esto ahorra recursos para mantener el índice, al tiempo que permite proporcionar los datos en las columnas incluidas para cubrir una consulta. Por lo tanto, si desea cubrir consultas, puede colocar los criterios de búsqueda para ubicar filas en las columnas ordenadas del índice, pero luego "incluir" columnas adicionales sin clasificar con datos que no sean de búsqueda. Definitivamente ayuda a reducir la cantidad de clasificación y fragmentación en el mantenimiento del índice.
fuente
Las razones por las cuales (incluyendo los datos en el nivel de hoja del índice) se han explicado muy bien. La razón por la que da dos sacudidas al respecto es que, cuando ejecuta su consulta, si no tiene las columnas adicionales incluidas (nueva característica en SQL 2005), el servidor SQL tiene que ir al índice agrupado para obtener las columnas adicionales lo que lleva más tiempo y agrega más carga al servicio de SQL Server, a los discos y a la memoria (la memoria caché del búfer para ser específica) a medida que se cargan nuevas páginas de datos en la memoria, lo que puede eliminar otros datos que se necesitan con mayor frecuencia fuera de la memoria caché del búfer.
fuente
Una consideración adicional que no he visto en las respuestas ya dadas, es que las columnas incluidas pueden ser de tipos de datos que no están permitidos como columnas de clave de índice, como varchar (max).
Esto le permite incluir tales columnas en un índice de cobertura. Recientemente tuve que hacer esto para proporcionar una consulta generada por nHibernate, que tenía muchas columnas en SELECT, con un índice útil.
fuente
Una razón para preferir
INCLUDE
a las columnas clave si no necesita esa columna en la clave es la documentación. Eso hace que la evolución de los índices sea mucho más fácil en el futuro.Considerando tu ejemplo:
Ese índice es mejor si su consulta se ve así:
Por supuesto, no debe colocar columnas
INCLUDE
si puede obtener un beneficio adicional al tenerlas en la parte clave. Las dos consultas siguientes preferirían lacol2
columna en la clave del índice.Supongamos que este no es el caso y tenemos
col2
en laINCLUDE
cláusula porque simplemente no hay beneficio de tenerlo en la parte del árbol del índice.Avance rápido algunos años.
Necesita ajustar esta consulta:
Para optimizar esa consulta, el siguiente índice sería excelente:
Si verifica qué índices tiene en esa tabla, su índice anterior aún podría estar allí:
Ahora lo sabe
Col2
yCol3
no forma parte del árbol de índice y, por lo tanto, no se utiliza para reducir el rango del índice de lectura ni para ordenar las filas. Es bastante seguro agregarloanother_column
al final de la parte clave del índice (despuéscol1
). Hay poco riesgo de romper algo:Ese índice se hará más grande, lo que todavía tiene algunos riesgos, pero generalmente es mejor extender los índices existentes en comparación con la introducción de nuevos.
Si tuviera un índice sin
INCLUDE
, no podría saber qué consultas rompería agregandoanother_col
justo despuésCol1
.¿Qué sucede si agregas
another_col
entreCol1
yCol2
? ¿Otras consultas sufrirán?Hay otros "beneficios" de
INCLUDE
las columnas de clave vs. vs. si agrega esas columnas solo para evitar recuperarlas de la tabla . Sin embargo, considero que el aspecto de la documentación es el más importante.Para responder tu pregunta:
Si agrega una columna al índice con el único propósito de tener esa columna disponible en el índice sin visitar la tabla, póngala en la
INCLUDE
cláusula.Si agregar la columna a la clave de índice brinda beneficios adicionales (por ejemplo, para
order by
o porque puede reducir el rango del índice de lectura), agréguelo a la clave.Puedes leer una discusión más larga sobre esto aquí:
https://use-the-index-luke.com/blog/2019-04/include-columns-in-btree-indexes
fuente
Existe un límite para el tamaño total de todas las columnas integradas en la definición del índice. Dicho esto, nunca he tenido que crear un índice tan amplio. Para mí, la mayor ventaja es el hecho de que puede cubrir más consultas con un índice que ha incluido columnas, ya que no tienen que definirse en ningún orden en particular. Pensar es como un índice dentro del índice. Un ejemplo sería el StoreID (donde StoreID es de baja selectividad, lo que significa que cada tienda está asociada con muchos clientes) y luego los datos demográficos del cliente (Apellido, Nombre, Fecha de nacimiento): si solo alinea esas columnas en este orden (StoreID, Apellido) , FirstName, DOB), solo puede buscar eficientemente clientes para los que conozca StoreID y LastName.
Por otro lado, definir el índice en StoreID e incluir las columnas LastName, FirstName, DOB le permitiría en esencia hacer dos predicados de índice de búsqueda en StoreID y luego buscar predicado en cualquiera de las columnas incluidas. Esto le permitiría cubrir todas las permutaciones de búsqueda posibles siempre que comience con StoreID.
fuente