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.

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 .


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.