Dziwne zachowanie agregacji strumienia

11

Pytanie:

declare @X xml = '
<item ID = "0"/>
<item ID = "1"/>
<item/>
<item/>';

select I.X.value('@ID', 'int')
from @X.nodes('/item') as I(X);

Wynik:

-----------
0
1
NULL
NULL

Plan wykonania:

wprowadź opis zdjęcia tutaj

Górna gałąź niszczy XML do czterech wierszy, a dolna gałąź pobiera wartość atrybutu ID.

To, co wydaje mi się dziwne, to liczba wierszy zwróconych przez operatora Stream Aggregate. 2 wiersze pochodzące z filtru to IDatrybut z pierwszego i drugiego itemwęzła w pliku XML. Agregacja strumienia zwraca cztery wiersze, po jednym dla każdego wiersza wejściowego, skutecznie zmieniając łączenie wewnętrzne w łączenie zewnętrzne.

Czy jest to coś, co robi agregacja strumieniowa również w innych okolicznościach, czy może jest to po prostu coś dziwnego podczas wykonywania zapytań XML?

W wersji XML planu zapytań nie widzę żadnych wskazówek, że agregacja strumieniowa powinna zachowywać się inaczej niż jakakolwiek inna agregacja strumieniowa, którą zauważyłem wcześniej.

Mikael Eriksson
źródło

Odpowiedzi:

13

Agregat jest agregatem skalarnym (bez grup według klauzul). Są one zdefiniowane w SQL Server, aby zawsze tworzyły wiersz, nawet jeśli dane wejściowe są puste.

Na przykład dla agregatu skalarnego , MAXbrak wierszy wynosi NULL, COUNTbrak wierszy wynosi na przykład zero. Optymalizator wie o tym wszystko i może przekształcić łączenie zewnętrzne w łączenie wewnętrzne w odpowiednich okolicznościach.

-- NULL for a scalar aggregate
SELECT MAX(V.v) FROM (VALUES(1)) AS V (v) WHERE V.v = 2;

-- No row for a vector aggregate
SELECT MAX(V.v) FROM (VALUES(1)) AS V (v) WHERE V.v = 2 GROUP BY ();

Aby uzyskać więcej informacji na temat agregatów, zobacz mój artykuł Zabawa z agregatami skalarnymi i wektorowymi .

Paul White 9
źródło
10

Trzeba tutaj pamiętać, że plany wykonania zasysają dane.

Tak więc operator zagnieżdżonej pętli wywołuje agregację strumienia 4 razy. Agregacja strumienia również wywołuje Filtr 4 razy, ale otrzymuje wartość tylko dwa razy.

Tak więc Stream Aggregate podaje cztery wartości. Dwa razy daje wartość, a dwa razy daje Null.

Rob Farley
źródło