¿Por qué la creación de este nuevo índice mejoró tanto el rendimiento cuando el índice existente incluía todas las columnas en el nuevo índice?

19

Tengo tablas Log y LogItem; Estoy escribiendo una consulta para obtener algunos datos de ambos. Hay miles de Logsy cada uno Logpuede 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 whereclá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.

Nate
fuente
Antes de crear el índice no agrupado adicional, ¿qué mostró el plan de ejecución real para el uso del índice?
Thomas Stringer
¿Qué es el rendimiento mejorado en un 100%?
@ Tiburón Buena pregunta, no estoy seguro. Esta es mi primera situación de depuración de rendimiento. Me aseguraré de agarrar eso en el futuro. Todo lo que dijo fue 'Índice faltante' y dijo qué campos.
@JeffO Esto es lo que dijo SSMS: "El procesador de consultas estima que implementar el siguiente índice podría mejorar el costo de la consulta en un 100%".

Respuestas:

21

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 de column1y column2. Pero si lo sabe column1y column2también, ubicar la rama correcta en el árbol es obvio.

GSerg
fuente
¿Sería seguro asumir (en general) que necesito un índice por conjunto de cláusulas "dónde" que van a llegar a esa tabla?
Una vez hice una aceleración masiva de la consulta de otra persona simplemente asegurándome de que usara el índice en el orden correcto.
1
@Nate Broadly, sí. Algunos wheres pueden superponerse, por lo que puede tener un índice que cubra varios wheres; o puede ignorar alguna parte de una wherecláusula porque la indexación en una determinada columna no va a ayudar de todos modos (baja selectividad); pero en general sí.
@Nate No desea tener más índices de los necesarios. Cada índice que SQL debe mantener agrega una sobrecarga propia. Si puede reordenar sus cláusulas WHERE para que coincidan con las primeras N columnas en un índice existente, eso lo acercará mucho sin agregar índices adicionales.
Ese Chuck Guy el
1
@ChuckBlumreich El orden de las columnas en las whereclá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 las wherecolumnas requeridas como sus primeras columnas.
12

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 ParentLogIDy DatabaseModified, 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) .

Branko Dimitrijevic
fuente
Entonces, si tengo Columns (a, b, c, d, e, f)y la mayoría de las consultas son ... WHERE A IN(...) AND B = 3mi índice, Index(a,b,c,d)es bueno, pero no ayuda si lo tengo, ... WHERE A IN (...) AND D = 5por eso mi nuevo índice que hice, Index(a,d)mejoró tanto el rendimiento, ¿verdad?
8
@Nate - correcto. Piense en ello como una guía telefónica. Si conoce el nombre de alguien, es imposible encontrarlo sin mirar todo el libro, ya que está organizado en Apellido, Nombre
JNK