El índice no agrupado que falta ya forma parte del índice agrupado

9

Estoy depurando una consulta de ejecución lenta y en el plan de ejecución se sugiere un índice no agrupado, con un impacto de 51.6648. Sin embargo, el índice no agrupado solo incluye columnas que ya están en el índice agrupado compuesto de clave primaria (PK).

¿Podría ser esto debido al orden de las columnas en el índice? es decir, si las columnas en el índice agrupado no están en orden de más selectivo a menos, entonces ¿hay potencial para que un índice no agrupado mejore el rendimiento?

Además, el índice no agrupado solo contiene dos de las tres columnas PK con el tercero agregado como una columna incluida. ¿Es la includeotra razón por la cual el uso del índice no agrupado podría ser más óptimo?

A continuación se muestra un ejemplo de las estructuras de tabla con las que estoy trabajando:

Mesas-

Retailers (
    RetailerID int PK, 
    name ...)

Retailer_Relation_Types (
    RelationType smallint PK, 
    Description nvarchar(50) ...)

Retailer_Relations (
    RetailerID int PK FK, 
    RelatedRetailerID int PK FK, 
    RelationType smallint PK FK, 
    CreatedOn datetime ...)

La tabla Retailer_Relationstiene el siguiente índice PK compuesto y el índice sugerido

CONSTRAINT PK_Retailer_Relations 
PRIMARY KEY CLUSTERED (
    RetailerID ASC, 
    RelatedRetailerID ASC, 
    RelationType ASC
    ) ON [PRIMARY]

CREATE NONCLUSTERED INDEX <NameOfIndex> 
ON Retailer_Relations (
    RetailerID, 
    RelationType
    ) 
INCLUDE (
    RelatedRetailerID
    )
Fletch
fuente

Respuestas:

12

La tabla Retailer_Relations tiene el siguiente índice PK compuesto y el índice sugerido:

Si bien los índices faltantes podrían ser útiles y definitivamente podrían funcionar, no dedicaría demasiado tiempo a los índices faltantes, estas sugerencias se crean en el plan de ejecución estimado, no en el plan de ejecución real.

Más precisamente, estas sugerencias de índice se basan en la premisa de reducir el costo de Query Bucks ™ utilizado por los operadores en el plan. El optimizador calcula los costos estimados y agrega las sugerencias de índice que faltan en consecuencia.

Como resultado, podrían estar muy equivocados. Si no está seguro de si va a ayudar, lo mejor que puede hacer es probar la situación antes y después. Puede hacer esto agregando la declaración SET STATISTICS IO, TIME ON;antes de ejecutar la consulta.

Además, puede usar el analizador de estadísticas para que sea más fácil leer estas estadísticas.

¿Podría ser esto debido al orden de las columnas en el índice?

Eso es correcto, crear el índice que falta puede mejorar la selectividad en las consultas, por ejemplo, si su consulta se ve así:

SELECT  RelatedRetailerID
FROM Retailer_Relations 
WHERE
RetailerID = 5 AND
RelationType = 20;

o así:

SELECT  RelatedRetailerID
FROM Retailer_Relations 
ORDER BY
RetailerID,
RelationType;

El razonamiento detrás de esto es que ambos índices podrían buscar en RetailerID, esa parte no va a cambiar. Pero, ¿qué pasa si se aplican filtros / pedidos adicionales en RelationType? Estaría por todas partes en el índice agrupado, como resultado de ser el tercer valor clave, no el segundo valor clave. Y como sabemos, es el segundo valor clave en el NCI.

De acuerdo, pero ¿cuándo o cómo mejoraría la consulta el índice no agrupado?

Un par de casos podrían ser:

  • Si relacionType filtra muchos valores, la E / S residual podría ser alta, lo que daría como resultado la posible necesidad del índice no agrupado (Consulta # 1)
  • Se produce un pedido en las dos columnas (unidireccional) y el conjunto de resultados es grande (consulta n.º 2).
  • Como @AaronBertrand mencionó: si la diferencia de tamaño de CI en comparación con el NCI es de una cantidad considerable, agregar el NCI reducirá las páginas leídas por consultas que se benefician de él.

Nota al margen del NCI

Como nota al margen, agregar las columnas clave a la lista de inclusión en su NCI no es exactamente necesario, ya que las columnas clave CI se incluyen automáticamente en todos los índices no agrupados.

Puede optar por hacerlo si no está seguro de si el índice agrupado seguirá siendo el mismo y desea que la columna siempre se incluya.

Con respecto a la consulta en sí, si agregó el plan de ejecución a través de PasteThePlan , podríamos brindarle más información sobre la indexación / mejora de la consulta.


Pruebas

Crear tabla y agregar algunas filas

CREATE TABLE Retailer_Relations (
    RetailerID int , 
    RelatedRetailerID int , 
    RelationType smallint, 
    CreatedOn datetime,
    CONSTRAINT PK_Retailer_Relations 
PRIMARY KEY CLUSTERED (
    RetailerID ASC, 
    RelatedRetailerID ASC, 
    RelationType ASC
    ) ON [PRIMARY])


    DECLARE @I Int = 1
    WHILE @I < 1000
    BEGIN
    INSERT INTO Retailer_Relations(RetailerID,RelatedRetailerID,RelationType,CreatedOn)
    VALUES(@I,@I,@I,GETDATE()
    )
    set @I += 1
    END

Consulta # 1

    SELECT  RelatedRetailerID
FROM Retailer_Relations 
WHERE
RetailerID = 5 AND
RelationType = 20;

Plan sin índice aquí

Mientras está haciendo una búsqueda, está haciendo una búsqueda en RetailerID. Luego está emitiendo un predicado de E / S residual en RelationType

Agrega el índice

CREATE NONCLUSTERED INDEX IX_TEST
ON Retailer_Relations (
    RetailerID, 
    RelationType
    ) 
INCLUDE (
    RelatedRetailerID
    )

El predicado residual se ha ido, todo sucede en un predicado de búsqueda, en ambas columnas.

Plan de ejecución

Con la segunda consulta, la utilidad del índice agregado se vuelve aún más obvia:

SELECT  RelatedRetailerID
FROM Retailer_Relations 
ORDER BY
RetailerID,
RelationType;

Planifique sin el índice, con un operador Ordenar:

ingrese la descripción de la imagen aquí

Planifique con el índice, el uso del índice elimina el operador de clasificación

ingrese la descripción de la imagen aquí

Randi Vertongen
fuente
1
Gracias Randi, marcaré esto como la respuesta, pero solo quería preguntarle si está diciendo que la sugerencia del índice que falta se basa en el plan de ejecución estimado. Pregunto esto ya que se muestra en el Plan de ejecución real en SS2016.
Fletch
1
Me preguntaba si eso es lo que estabas diciendo, gracias por aclarar.
Fletch