Arrojemos un millón de filas en una tabla temporal junto con algunas columnas:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (PK)
);
INSERT INTO #174860 WITH (TABLOCK)
SELECT RN
, RN % 1000
, RN % 10000
FROM
(
SELECT TOP 1000000 ROW_NUMBER () OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values v1,
master..spt_values v2
) t;
CREATE INDEX IX_174860_IX ON #174860 (COL1) INCLUDE (COL2);
Aquí tengo un índice agrupado (por defecto) en la PK
columna. Hay un índice no agrupado COL1
que tiene una columna clave de COL1
e incluye COL2
.
Considere la siguiente consulta:
SELECT *
FROM #174860
WHERE PK >= 15000 AND PK < 15005
AND COL2 = 5000;
Aquí no estoy usando BETWEEN
porque Aaron Bertrand está dando vueltas a esta pregunta.
¿Cómo debe optimizar SQL Server esa consulta? Bueno, sé que el filtro PK
activado reducirá el conjunto de resultados a cinco filas. El servidor SQL puede usar el índice agrupado para saltar a esas cinco filas en lugar de leer todos los millones de filas de la tabla. Sin embargo, el índice agrupado solo tiene la columna PK como una columna clave. Una vez que la fila se lee en la memoria, debemos aplicar el filtro COL2
. Aquí, PK
es un predicado de búsqueda y COL2
es un predicado.
El servidor SQL encuentra cinco filas usando el predicado de búsqueda y reduce aún más esas cinco filas a una fila con el predicado normal.
Si defino el índice agrupado de manera diferente:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (COL2, PK)
);
Y ejecuto la misma consulta obtengo resultados diferentes:
En este caso, SQL Server puede buscar utilizando ambas columnas en la WHERE
cláusula. Se lee exactamente una fila de la tabla utilizando las columnas clave.
Para un ejemplo más, considere esta consulta:
SELECT *
FROM #174860
WHERE COL1 = 500
AND COL2 = 3545;
El índice IX_174860_IX es un índice de cobertura porque contiene todas las columnas necesarias para la consulta. Sin embargo, solo COL1
es una columna clave. SQL Server puede buscar con esa columna para encontrar las 1000 filas con un COL1
valor coincidente . Puede filtrar aún más esas filas en la COL2
columna para reducir el conjunto de resultados finales a 0 filas.