Je pose cette question afin de mieux comprendre le comportement de l'optimiseur et de comprendre les limites autour des spools d'index. Supposons que je mette des entiers de 1 à 10000 dans un tas:
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;
Et forcez une boucle imbriquée à se joindre à MAXDOP 1
:
SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);
Il s'agit d'une action plutôt hostile à entreprendre envers SQL Server. Les jointures de boucles imbriquées ne sont souvent pas un bon choix lorsque les deux tables n'ont pas d'index pertinents. Voici le plan:
La requête prend 13 secondes sur ma machine avec 100000000 lignes extraites de la bobine de table. Cependant, je ne vois pas pourquoi la requête doit être lente. L'optimiseur de requêtes a la possibilité de créer des index à la volée via des spools d'index . Cette requête semble être un candidat parfait pour une bobine d'index.
La requête suivante renvoie les mêmes résultats que la première, possède une bobine d'index et se termine en moins d'une seconde:
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);
Cette requête a également une bobine d'indexation et se termine en moins d'une seconde:
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);
Pourquoi la requête d'origine n'a-t-elle pas de bobine d'index? Existe-t-il un ensemble d'indications ou d'indicateurs de trace documentés ou non qui lui donneront une file d'attente d'index? J'ai trouvé cette question connexe , mais elle ne répond pas entièrement à ma question et je ne peux pas faire fonctionner l'indicateur de trace mystérieux pour cette requête.