2009-08-20 10 views
333

Mientras estudiaba para el examen 70-433 noté que puede crear un índice de cobertura de una de las siguientes dos maneras.¿Por qué usar la cláusula INCLUDE cuando se crea un índice?

CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3) 

- O -

CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3) 

La cláusula INCLUDE es nuevo 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?

Respuesta

290

Si la columna no está en el DONDE/JOIN/GROUP BY/ORDER BY, pero sólo en la lista de columnas en la cláusula SELECT.

La cláusula INCLUDE agrega los datos al nivel más bajo/hoja, en lugar de en el árbol de índice. Esto hace que el índice sea más pequeño porque no forma parte del árbol

Esto significa que no es realmente útil para predicados, clasificación, etc., como mencioné anteriormente. Sin embargo, se puede ser útil si usted tiene una búsqueda residual en un par de filas de la columna (s) clave

Another MSDN article with a worked example

+4

Entonces, ¿esta sería una técnica para crear una versión menos costosa de un índice cubierto? – JMarsch

+1

@gbn, ¿te importaría explicar esta oración con más detalle y explicar por qué significa que la cláusula include no es útil para ordenar, etc. ?: "La cláusula INCLUDE agrega los datos en el nivel más bajo/hoja, en lugar de en el índice Esto hace que el índice sea más pequeño porque no forma parte del árbol " –

+2

@JMarsch: perdón por la respuesta tardía, pero sí, esto es exactamente lo que es. – gbn

15

columnas de índice básicos están ordenados, sino que incluía columnas no están ordenados. Esto ahorra recursos para mantener el índice, al mismo 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 ordenar 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.

176

Se podría utilizar el incluir para añadir una o más columnas para el nivel hoja de un índice no agrupado, si al hacerlo, puede "cubrir" sus consultas.

Imagínese que usted necesita para consultar el ID de un empleado, ID de departamento y apellido.

SELECT EmployeeID, DepartmentID, LastName 
FROM Employee 
WHERE DepartmentID = 5 

Si le sucede que tiene un índice no agrupado en (EmployeeID, DepartmentID), una vez que encuentre los empleados de un departamento dado, ahora tiene que hacer "marcador de búsqueda" para obtener el registro real empleado completa , solo para obtener la columna de apellido. Eso puede ser bastante caro en términos de rendimiento, si encuentra muchos empleados.

Si se hubiera incluido esa apellido en su índice:

CREATE NONCLUSTERED INDEX NC_EmpDep 
    ON Employee(EmployeeID, DepartmentID) 
    INCLUDE (Lastname) 

continuación, toda la información que necesita está disponible en el nivel hoja del índice no agrupado. Sólo mediante la búsqueda en el índice no agrupado y la búsqueda de sus empleados para un determinado departamento, que tiene toda la información necesaria, y la búsqueda de marcador para cada empleado que se encuentra en el índice ya no es necesario -> ahorrará mucho tiempo.

Obviamente, no puede incluir todas las columnas en cada índice no agrupado, pero si tiene consultas a las que falta una o dos columnas para "cubrir" (y que se usan mucho), puede ser muy útil para INCLUIR aquellos en un índice adecuado no agrupado.

+17

¿Estás seguro de que usarías este índice? ¿Por qué EmployeeID? ¿Solo necesita DepartmentID en las columnas clave? Ha sido citado aquí como authoratitive: http://stackoverflow.com/q/6187904/27535 – gbn

+3

Su explicación es buena, pero en realidad no se alinea con el caso de uso que describe. Las columnas de clave deben estar en el filtro o las teclas 'JOIN' en la consulta, y los 'INCLUDE's deben ser los datos que está recuperando pero no ordenando. – JNK

+10

En primer lugar, el empleado de índice (ID de empleado, ID de departamento) no se utilizará para filtrar DepartmentID = 5. Debido a que su orden no coincide – AnandPhadke

5

Las razones por las (incluyendo los datos en el nivel de hoja del índice) han sido bien explicada.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 función en SQL 2005), el SQL Server debe ir al índice agrupado para obtener las columnas adicionales. lo cual 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 es específica) a medida que se cargan nuevas páginas de datos en la memoria, lo que puede alejar otros datos más necesarios de la memoria caché del búfer.

+0

¿hay alguna manera de demostrar que en realidad está utilizando menos memoria? es lo que también esperaría, pero obtengo algo de estática sobre esto en el trabajo – Asken

+0

Dado que tiene que cargar la página del montón o del índice agrupado en la memoria, así como en la página de índice, lo que significa que está poniendo datos duplicados en memoria, las matemáticas se vuelven bastante simples. En cuanto a una forma de medirlo específicamente, no, no. – mrdenny

2

Hay un límite para el tamaño total de todas las columnas incluidas en la definición del índice. Sin embargo, dicho esto, nunca tuve que crear un índice tan amplio. Para mí, la ventaja más grande es el hecho de que puede cubrir más consultas con un índice que incluye columnas, ya que no tienen que definirse en un orden en particular. Pensar es como un índice dentro del índice. Un ejemplo sería el StoreID (donde StoreID tiene una baja selectividad, lo que significa que cada tienda está asociada a muchos clientes) y datos demográficos del cliente (Apellido, Nombre, Fecha de nacimiento): Si alinea esas columnas en este orden (ID de tienda) , Apellido, Nombre, Fecha de nacimiento), solo puede buscar eficientemente clientes para los que conoce StoreID y LastName.

Por otro lado, definir el índice en StoreID e incluir las columnas Apellido, Nombre y Fecha de nacimiento le permitiría en esencia hacer dos predicados í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.

4

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 dichas columnas en un índice de cobertura. Hace poco tuve que hacer esto para proporcionar una consulta generada nHibernate, que tenía muchas columnas en SELECT, con un índice útil.

16

Esta discusión se está perdiendo el punto importante: La cuestión no es si los "no-clave-columnas" son mejores para incluir como índice de -Columnas o como incluido -Columnas.

La pregunta es qué tan costoso es usar el mecanismo de inclusión para incluir columnas que no son realmente necesarias en el índice? ? (Por lo general, no forma parte de where-clauses, pero a menudo se incluye en selects). Por lo que su dilema es siempre:

  1. Uso índice en ID1, ID2 ... idN solos o
  2. Uso índice en ID1, ID2 ... idN además incluir col1, col2 ... Cöln

Dónde: ID1, ID2 ... idN son utilizados a menudo en columnas restricciones y col1, col2 ... Cöln se selecciona a menudo columnas, pero por lo general no utiliza en restricciones

(La opción de incluir todas estas columnas como parte de la clave de índice es siempre tonta (a menos que también se utilicen en restricciones), porque siempre sería más costoso de mantener ya que el índice debe actualizarse y ordenarse incluso cuando las "teclas" no han cambiado).

¿Entonces use la opción 1 o 2?

Respuesta: Si la tabla rara vez se actualiza - inserta en su mayoría en/elimina de - entonces es relativamente barato de utilizar el mecanismo de incluir a incluir algunos "columnas calientes" (que se utilizan a menudo en selecciona - pero no a menudo se usa en restricciones) ya que las inserciones/eliminaciones requieren que el índice se actualice/ordene de todos modos y, por lo tanto, se requiere poca sobrecarga adicional para almacenar algunas columnas adicionales mientras se actualiza el índice. La sobrecarga es la memoria extra y la CPU utilizada para almacenar información redundante en el índice.

Si las columnas que considere a añadir al-columnas incluidas son actualizados con frecuencia (sin las claves en índices -Columnas proceso de actualización) - o - si es así que muchos de los que el índice se convierte en cerca de una copia de su tabla - use la opción 1, sugeriría Además, si agrega ciertas columnas de inclusión para que no se produzca ninguna diferencia en el 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 teclas (id1, id2 ... idN) también puede ser de cierta importancia.

en cuenta que si una columna - que se añade como un incluido -column de índice - se utiliza en el restricción: Mientras el índice, como tal, puede ser utilizado (basado en restricción contra indiciados clave -columnas) - entonces SQL Server está haciendo coincidir la restricción de columna con el índice (leaf-node-values) en lugar de ir por el camino costoso alrededor de la tabla.

Cuestiones relacionadas