Estoy haciendo esta pregunta para comprender mejor el comportamiento del optimizador y comprender los límites en torno a los carretes de índice. Supongamos que pongo enteros del 1 al 10000 en un montón:
CREATE TABLE X_10000 (ID INT NOT NULL);
truncate table X_10000;
INSERT INTO X_10000 WITH (TABLOCK)
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
Y forzar una unión de bucle anidado con MAXDOP 1
:
SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);
Esta es una acción poco amigable que se debe tomar hacia SQL Server. Las uniones de bucle anidado a menudo no son una buena opción cuando ambas tablas no tienen índices relevantes. Aquí está el plan:
La consulta tarda 13 segundos en mi máquina con 100000000 filas obtenidas del carrete de la tabla. Sin embargo, no veo por qué la consulta debe ser lenta. El optimizador de consultas tiene la capacidad de crear índices sobre la marcha a través de carretes de índice . Esta consulta parece ser un candidato perfecto para un carrete de índice.
La siguiente consulta devuelve los mismos resultados que la primera, tiene un carrete de índice y finaliza en menos de un segundo:
SELECT *
FROM X_10000 a
CROSS APPLY (SELECT TOP (9223372036854775807) b.ID FROM X_10000 b WHERE a.ID = b.ID) ca
OPTION (LOOP JOIN, MAXDOP 1);
Esta consulta también tiene un carrete de índice y termina en menos de un segundo:
SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID >= b.ID AND a.ID <= b.ID
OPTION (LOOP JOIN, MAXDOP 1);
¿Por qué la consulta original no tiene un carrete de índice? ¿Hay algún conjunto de sugerencias documentadas o indocumentadas o marcas de seguimiento que le den un carrete de índice? Encontré esta pregunta relacionada , pero no responde completamente a mi pregunta y no puedo hacer que la misteriosa marca de seguimiento funcione para esta consulta.
fuente