Tengo tablas Log y LogItem; Estoy escribiendo una consulta para obtener algunos datos de ambos. Hay miles de Logs
y cada uno Log
puede tener hasta 125LogItems
La consulta en cuestión es complicada, así que la estoy omitiendo (si alguien piensa que es importante, probablemente pueda publicarla), pero cuando ejecuté el plan de consulta estimada de SSMS, me dijo que un nuevo índice no agrupado mejoraría el rendimiento hasta un 100% .
Existing Index: Non-clustered
Key Colums (LogItem): ParentLogID, DateModified, Name, DatabaseModified
Query Plan Recommendation
CREATE NONCLUSTERED INDEX [LogReportIndex]
ON [dbo].[LogItem] ([ParentLogID],[DatabaseModified])
Solo por diversión, creé este nuevo índice y ejecuté la consulta y para mi sorpresa, ahora toma ~ 1 segundo para que mi consulta se ejecute, cuando antes era más de 10 segundos.
Supuse que mi índice existente cubriría esta nueva consulta, así que mi pregunta es ¿por qué la creación de un nuevo índice en las únicas columnas utilizadas en mi nueva consulta mejoró el rendimiento? ¿Debo tener un índice para cada combinación única de columnas utilizada en mis where
cláusulas?
nota: No creo que esto se deba a que el Servidor SQL está almacenando en caché mis resultados, ejecuté la consulta unas 25-30 veces antes de crear el índice y de manera constante tardó 10-15 segundos, después del índice ahora es consistente ~ 1 o menos.
fuente
Respuestas:
El orden de las columnas en un índice es importante. Si el filtrado requiere las columnas 1 y 4 del índice, el índice no ayudará. Solo es útil cuando se filtra por las primeras N columnas consecutivas.
Esto se debe a que el índice es un árbol. No puede seleccionar eficientemente todos los nodos del árbol donde
column3 = something
, porque están dispersos en todos los demás lugares, pertenecientes a diferentes valores decolumn1
ycolumn2
. Pero si lo sabecolumn1
ycolumn2
también, ubicar la rama correcta en el árbol es obvio.fuente
where
s pueden superponerse, por lo que puede tener un índice que cubra varioswhere
s; o puede ignorar alguna parte de unawhere
cláusula porque la indexación en una determinada columna no va a ayudar de todos modos (baja selectividad); pero en general sí.where
cláusulas no es importante. El servidor siempre los organizará para aprovechar al máximo los índices existentes. Es solo una cuestión de tener un índice que incluya todas laswhere
columnas requeridas como sus primeras columnas.La ventaja de un índice es lo que importa.
Mientras su consulta esté "cubierta" por un borde de ataque de un índice, será eficiente. Los índices de bases de datos generalmente se implementan como B-Trees y la estructura del B-Tree dicta que la búsqueda debe realizarse en un cierto orden, por lo que el orden de los campos en el índice compuesto es importante.
Si tiene "agujeros", por ejemplo, si busca
ParentLogID
yDatabaseModified
, pero solo tiene un índice activado{ParentLogID, DateModified, Name, DatabaseModified}
, entonces solo la{ParentLogID}
parte del índice puede utilizarse de manera eficiente.(NOTA: Algunos DBMS pueden utilizar la
{DatabaseModified}
porción a través de "omitir escaneo", pero incluso si su DBMS lo hace es mucho menos eficiente que el acceso al índice regular) .fuente
Columns (a, b, c, d, e, f)
y la mayoría de las consultas son... WHERE A IN(...) AND B = 3
mi índice,Index(a,b,c,d)
es bueno, pero no ayuda si lo tengo,... WHERE A IN (...) AND D = 5
por eso mi nuevo índice que hice,Index(a,d)
mejoró tanto el rendimiento, ¿verdad?