Estou fazendo essa pergunta para entender melhor o comportamento do otimizador e entender os limites dos spools de índice. Suponha que eu coloque números inteiros de 1 a 10000 em um heap:
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;
E forçar uma junção aninhada com MAXDOP 1
:
SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);
Esta é uma ação bastante hostil a ser tomada em relação ao SQL Server. Junções de loop aninhadas geralmente não são uma boa opção quando ambas as tabelas não possuem índices relevantes. Aqui está o plano:
A consulta leva 13 segundos na minha máquina com 100000000 linhas buscadas no spool da tabela. No entanto, não vejo por que a consulta precisa ser lenta. O otimizador de consulta tem a capacidade de criar índices dinamicamente através de spools de índice . Essa consulta parece ser uma candidata perfeita para um spool de índice.
A consulta a seguir retorna os mesmos resultados que a primeira, possui um spool de índice e termina em menos de um 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);
Essa consulta também possui um spool de índice e termina em menos de um 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 que a consulta original não possui um spool de índice? Existe algum conjunto de dicas ou sinalizadores de rastreamento documentados ou não documentados que fornecerão um spool de índice? Encontrei essa pergunta relacionada , mas ela não responde totalmente à minha pergunta e não consigo que o sinalizador de rastreamento misterioso funcione para esta consulta.