Pregunta

Recientemente encontré un índice en una base de datos que mantengo y que tenía la forma:

CREATE INDEX [IX_Foo] ON [Foo]
( Id ASC )
INCLUDE 
( SubId )

En este caso particular, el problema de rendimiento que estaba encontrando (un filtrado SELECT lento tanto en Id como en SubId) podría solucionarse simplemente moviendo la columna SubId al índice propiamente dicho en lugar de como una columna incluida.

Sin embargo, esto me hizo pensar que no entiendo en absoluto el razonamiento detrás de las columnas incluidas, cuando, en general, podrían ser simplemente parte del índice mismo.Incluso si no me importa especialmente que los elementos estén en el índice en sí, ¿hay alguna desventaja en tener una columna en el índice en lugar de simplemente incluirse?

Después de investigar un poco, soy consciente de que existen una serie de restricciones sobre lo que se puede incluir en una columna indexada (ancho máximo del índice y algunos tipos de columnas que no se pueden indexar como "imagen").En estos casos puedo ver que se vería obligado a incluir la columna en los datos de la página de índice.

Lo único que se me ocurre es que si hay actualizaciones en SubId, no será necesario reubicar la fila si se incluye la columna (aunque sería necesario cambiar el valor en el índice).¿Hay algo más que me falta?

Estoy considerando revisar los otros índices de la base de datos y cambiar las columnas incluidas en el índice adecuado siempre que sea posible.¿Sería esto un error?

Estoy interesado principalmente en MS SQL Server, pero también es bienvenida información sobre otros motores de base de datos.

¿Fue útil?

Solución

Las respuestas hasta ahora son todas correctas, pero es posible que no transmitan lo suficiente lo que se obtiene con un índice de cobertura.

En tu caso tienes una mesa. Foo y algunos campos, incluido un Id (que supongo que es la clave principal), y una SubId que es alguna identificación adicional de algún tipo.

También tienes un índice. IX_Foo que supongo que sólo tenía Id en ello por ahora.

Entonces ahora necesitas encontrar el SubId para Id=4.

SELECT Id, SubId
FROM Foo
WHERE Id=4
  • SQL Server examinará la instrucción SELECT y determinará si puede usarse IX_Foo
  • Luego buscará el valor. Id=4 en tu índice IX_Foo
  • cuando lo encuentra, ahora necesita el valor de SubId, también
  • el índice no agrupado IX_Foo contendrá el valor de la clave de agrupación
  • Al utilizar ese valor de clave de agrupación, SQL Server realizará una "búsqueda de marcadores" para ubicar la página de datos real donde se encuentra toda la fila de datos.
  • buscará esa página y extraerá el valor de SubId de eso
  • devolverá esos valores para satisfacer su consulta

El punto principal aquí es:una vez que SQL Server haya encontrado su Id=4 en el IX_Foo índice, luego necesitará realizar otra operación de E/S, una búsqueda de marcadores, para ir a buscar toda la fila de datos y poder encontrar el SubId valor.

Si tiene un índice de cobertura, p. IX_Foo también contiene SubId, se elimina esa E/S adicional para realizar la búsqueda de marcadores.Una vez que el valor Id=4 se encuentra en el IX_Foo índice, esa página de índice en su índice no agrupado también incluirá el valor de SubId - SQL Server ahora puede devolver esos dos valores que solicitó en su consulta SELECT sin tener que hacer una búsqueda de marcadores adicional (potencialmente costosa y, por lo tanto, lenta) solo para buscar otra columna de identificación.

Ese es el principal beneficio de cubrir índices: si solo necesita una o dos columnas adicionales, además de los valores de índice que está buscando, al incluir esos valores en el índice mismo, puede ahorrarse muchas búsquedas de marcadores y, por lo tanto, acelerar las cosas significativamente.Sin embargo, solo debes incluir muy pocos y pequeños fragmentos de información; ¡no dupliques las filas de datos completas en todos los índices no agrupados!Ese no es el punto.

ACTUALIZAR: la compensación es esta:si tiene un índice en (Id, SubId), todas las páginas del índice tienen ambas columnas: todo el árbol del índice.

Si INCLUYE (SubId), los campos SubId solo están presentes en el nivel de hoja.

Esto significa

  • SQL Server no puede buscar ni comparar en SubId (los valores no están en el árbol de índice)
  • Se utiliza menos espacio ya que los valores solo están en el nivel de la hoja.

Otros consejos

La razón para tener una columna adicional en un índice es por lo que cuando se hace una consulta que sólo requiere de las columnas utilizadas por el índice se puede cumplir con la consulta del índice por sí mismo. De esta manera se ahorra tiempo y recursos a volver a la mesa. Cuando esto sucede, se dice que el índice es un índice cubriendo para la consulta.

La razón puede que no desee hacer esta parte de la columna adicional el "índice adecuado" es porque cuando haces inserciones o actualizaciones en esa columna que es más probable que tenga que volver a ordenar las piezas del índice.

Uso de incluir en un índice permite el índice para ser usado como un índice de recubrimiento (es decir, determinadas consultas pueden ser satisfechos usando ese índice solo, sin tener que realizar una búsqueda de marcador en el índice agrupado), sin añadir esas columnas a la actual parte del árbol del índice, manteniendo así el tamaño del índice hacia abajo. (Las columnas incluidas solamente se añaden a los nodos de hoja del índice).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top