Dado el siguiente ejemplo:
IF OBJECT_ID('dbo.my_table') IS NOT NULL
DROP TABLE [dbo].[my_table];
GO
CREATE TABLE [dbo].[my_table]
(
[id] int IDENTITY (1,1) NOT NULL PRIMARY KEY,
[foo] int NULL,
[bar] int NULL,
[nki] int NOT NULL
);
GO
/* Insert some random data */
INSERT INTO [dbo].[my_table] (foo, bar, nki)
SELECT TOP (100000)
ABS(CHECKSUM(NewId())) % 14,
ABS(CHECKSUM(NewId())) % 20,
n = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
FROM
sys.all_objects AS s1
CROSS JOIN
sys.all_objects AS s2
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_my_table]
ON [dbo].[my_table] ([nki] ASC);
GO
Si busco todos los registros ordenados por [nki]
(Índice no agrupado):
SET STATISTICS TIME ON;
SELECT id, foo, bar, nki FROM my_table ORDER BY nki;
SET STATISTICS TIME OFF;
SQL Server Execution Times: CPU time = 266 ms, elapsed time = 493 ms
El optimizador elige el índice agrupado y luego aplica un algoritmo de clasificación.
Pero si lo fuerzo a usar el índice no agrupado:
SET STATISTICS TIME ON;
SELECT id, foo, bar, nki FROM my_table WITH(INDEX(IX_my_TABLE));
SET STATISTICS TIME OFF;
SQL Server Execution Times: CPU time = 311 ms, elapsed time = 188 ms
Luego usa un índice no agrupado con una búsqueda clave:
Obviamente, si el índice no agrupado se transforma en un índice de cobertura:
CREATE UNIQUE NONCLUSTERED INDEX [IX_my_table]
ON [dbo].[my_table] ([nki] ASC)
INCLUDE (id, foo, bar);
GO
Luego usa solo este índice:
SET STATISTICS TIME ON;
SELECT id, foo, bar, nki FROM my_table ORDER BY nki;
SET STATISTICS TIME OFF;
SQL Server Execution Times: CPU time = 32 ms, elapsed time = 106 ms
Pregunta
- ¿Por qué SQL Server usa el índice agrupado más un algoritmo de clasificación en lugar de usar un índice no agrupado, incluso si el tiempo de ejecución es un 38% más rápido en el último caso?
Respuestas:
Debido a que SQL Server utiliza un optimizador basado en costos basado en estadísticas, no en información de tiempo de ejecución.
Durante el proceso de estimación de costos para esta consulta, en realidad evalúa el plan de búsqueda, pero estima que tomará más esfuerzo. (Tenga en cuenta el "Costo estimado del subárbol" al pasar el mouse sobre SELECT en el plan de ejecución). Eso tampoco es necesariamente una mala suposición: en mi máquina de prueba, el plan de búsqueda toma 6 veces la CPU del tipo / escaneo.
Mire la respuesta de Rob Farley sobre por qué SQL Server podría costar más el plan de búsqueda.
fuente
Si comparara el número de lecturas requeridas en 100,000 búsquedas con lo que implica hacer una ordenación, podría tener una idea rápida de por qué el Optimizador de consultas calcula que CIX + Sort sería la mejor opción.
La ejecución de búsqueda termina siendo más rápida porque las páginas que se leen están en la memoria (incluso si borra el caché, tiene muchas filas por página, por lo que está leyendo las mismas páginas una y otra vez, pero con diferentes cantidades de fragmentación o diferente presión de memoria de otra actividad, este podría no ser el caso). Realmente no tomaría tanto tiempo hacer que CIX + Sort vaya más rápido, pero lo que está viendo es porque el costo de una lectura no tiene en cuenta el bajo costo relativo de ir a las mismas páginas repetidamente.
fuente
Decidí profundizar un poco en esta pregunta y descubrí algunos documentos interesantes que hablan sobre cómo y cuándo usar o tal vez mejor, no (forzar) el uso de un índice no agrupado.
Según lo sugerido por los comentarios de John Eisbrener , uno de los blogs más mencionados, incluso en otros blogs, es este interesante artículo de Kimberly L. Tripp:
pero no es el único, si estás interesado puedes echar un vistazo a estas páginas:
Como puede ver, todos se mueven alrededor del concepto del punto de inflexión .
Citado del artículo de KL Tripp
Cuando SQL Server usa un índice no agrupado en un montón, básicamente obtiene una lista de punteros a las páginas de la tabla base. Luego utiliza estos punteros para recuperar las filas con una serie de operaciones llamadas Búsquedas de ID de fila (RID). Esto significa que, al menos, usará tantas lecturas de página como el número de filas devueltas, y tal vez más. El proceso es algo similar con un índice agrupado como la tabla base, con el mismo resultado: más lecturas.
Pero, cuando se produce ese punto de inflexión?
Por supuesto, como la mayoría de las cosas en esta vida, depende ...
No, en serio, ocurre entre el 25% y el 33% del número de páginas en la tabla, dependiendo de cuántas filas por página. Pero hay más factores que debes considerar:
Citado del artículo de ITPRoToday
Ahora si ejecuto mis consultas nuevamente usando estadísticas IO:
La segunda consulta necesita más lecturas lógicas que la primera.
¿Debo evitar el índice no agrupado?
No, un índice agrupado puede ser útil, pero vale la pena tomarse un tiempo y hacer un esfuerzo adicional para analizar lo que está tratando de lograr con él.
Citado del artículo de KL Tripp
fuente