La superposición de los índices de cobertura e individuales en SQL Server
-
08-10-2019 - |
Pregunta
Tengo una pregunta relativa a las mejores prácticas para la indización en SQL Server (o cualquier RDBMS para el caso). Tome la siguiente tabla:
ProfileID int
Text nvarchar(50)
ProfileID
se une a una mesa Profile
. Para cada perfil, cada Text
debe ser único. Por lo tanto pongo una clave primaria cubierta en ambas columnas. Bien.
Sin embargo, también quiero ser capaz de consultar la tabla anterior por ProfileID
. Así que también puse un índice en ProfileID
también.
Esto significa que tengo un índice superpuestas. No sé si esto es un total desperdicio ya que no es un índice de la cubierta ya, o si es correcto, ya que el índice de la cubierta sería un hash de las dos columnas (o estoy mal entendido índices de cobertura)?
Editar:
crea el índice en el (ProfileID, Text)
orden. ¿Qué pasa si, pongamos por caso, había 3 columnas A, B, y C, que tenía un índice de cobertura sobre los 3. ¿Sería sólo benefician si nos preguntó en contra de "A" o "A, B, y C", pero no "B", o "C", o "B y C"?
Solución
un índice en (ProfileID, Text)
(en este orden) es un índice en ProfileID
también.
Es posible que aún desee crear un índice adicional sobre ProfileID
solamente, si desea un mayor rendimiento SELECT
en consultas que no implican Text
.
Sin embargo, esto tiene dos inconvenientes:
-
El mantenimiento de dos índices requiere más recursos y rendimiento de las consultas
DML
(INSERT
,UPDATE
,DELETE
) pueden sufrir -
Si se mezclan las consultas de los dos tipos, ambos índices se ocupan de la memoria caché y no puede haber más fallos de caché que con un solo índice.
No es un problema si la tabla es lo suficientemente pequeño como para caber en la memoria caché, junto con los dos índices.
El índice de la cubierta sería un hash de las dos columnas (o estoy malentendido índices de cobertura)?
Un índice que cubre realmente sería creada de esta manera:
CREATE INDEX ix_mytable_profile__text ON mytable (ProfileID) INCLUDE (Text)
De esta manera, Text
sólo se almacena en los nodos de nivel de hoja del índice.
Sin embargo, ya que se necesita un índice UNIQUE
, ambas columnas tienen que ser parte de la clave. Los nodos están ordenadas lexicográficamente en ProfileID
entonces Text
.
crea el índice en el orden (ProfileID de, texto). ¿Qué pasa si, pongamos por caso, había 3 columnas A, B, y C, que tenía un índice de cobertura sobre los 3. ¿Sería sólo benefician si nos preguntó en contra de "A" o "A, B, y C", pero no "B", o "C", o "B y C"?
CREATE INDEX ix_mytable_a_b_c ON mytable (a, b, c)
SELECT a, b, с
FROM mytable
WHERE a = 1
-- Index lookup, no table lookup. a is leading
SELECT a, b, с
FROM mytable
WHERE a = 1
AND b = 1
-- Index lookup, no table lookup. (a, b) are leading.
SELECT a, b, с
FROM mytable
WHERE b = 1
-- Index full scan (`b` is not leading), no table lookup
SELECT a, b, с
FROM mytable
WHERE c = 1
-- Index full scan (`c` is not leading), no table lookup
SELECT a, b, с, d
FROM mytable
WHERE a = 1
-- Index lookup, table tookup (d is not a part of the index).
SELECT a, b, с, d
FROM mytable
WHERE b = 1
-- Table full scan (there is no point in using index at all, neither for lookup nor for covering).