Zadaję to pytanie, aby lepiej zrozumieć zachowanie optymalizatora i zrozumieć ograniczenia wokół buforów indeksu. Załóżmy, że umieściłem na stercie liczby całkowite od 1 do 10000:
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;
I wymuś połączenie zagnieżdżonej pętli z MAXDOP 1
:
SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);
Jest to raczej nieprzyjazna czynność wobec SQL Server. Połączenia zagnieżdżonej pętli często nie są dobrym wyborem, gdy obie tabele nie mają żadnych odpowiednich indeksów. Oto plan:
Zapytanie zajmuje 13 sekund na mojej maszynie z pobranymi 100000000 wierszami ze szpuli tabeli. Nie rozumiem jednak, dlaczego zapytanie musi być wolne. Optymalizator zapytań ma możliwość tworzenia indeksów w locie za pośrednictwem buforów indeksów . To zapytanie wydaje się być idealnym kandydatem do buforowania indeksu.
Poniższe zapytanie zwraca te same wyniki co pierwsze, ma bufor buforowania i kończy się w niecałą sekundę:
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);
To zapytanie ma również bufor indeksu i kończy się w niecałą sekundę:
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);
Dlaczego oryginalne zapytanie nie ma buforu indeksu? Czy istnieje zestaw udokumentowanych lub nieudokumentowanych podpowiedzi lub flag śledzenia, który da bufor buforowy? Znalazłem to powiązane pytanie , ale nie w pełni odpowiada ono na moje pytanie i nie mogę zmusić tajemniczej flagi śledzenia do działania dla tego zapytania.
źródło