Поведение нечетного потока

11

Запрос:

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

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

Результат:

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

План выполнения:

введите описание изображения здесь

Верхняя ветвь разделяет XML на четыре строки, а нижняя ветвь выбирает значение для атрибута ID.

То, что кажется мне странным, это количество строк, возвращаемых оператором Stream Aggregate. 2 строки из фильтра - это IDатрибут первого и второго itemузлов в XML. Агрегат потока возвращает четыре строки, по одной для каждой входной строки, эффективно превращая внутреннее соединение во внешнее соединение.

Это то, что Stream Aggregate делает и в других обстоятельствах, или это просто что-то странное происходит при выполнении запросов XML?

Я не вижу никаких намеков в XML-версии плана запроса, что этот агрегат потока должен вести себя иначе, чем любой другой агрегат потока, который я заметил ранее.

Микаэль Эрикссон
источник

Ответы:

13

Агрегат является скалярным агрегатом (без группировки по выражению). Они определены в SQL Server, чтобы всегда создавать строки, даже если входные данные пусты.

Например, для скалярного агрегата, MAXв котором нет ни одной строки NULL, COUNTни одной строки не является ноль. Оптимизатор знает все об этом и может преобразовать внешнее соединение во внутреннее соединение в подходящих обстоятельствах.

-- 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 ();

Для получения дополнительной информации о агрегатах, см. Мою статью Fun With Scalar and Vector Aggregates .

Пол Уайт 9
источник
10

Здесь следует помнить, что планы выполнения высасывают данные.

Таким образом, оператор Nested Loop вызывает агрегат потока 4 раза. Stream Aggregate также вызывает фильтр 4 раза, но получает значение только дважды.

Таким образом, агрегат потока дает четыре значения. Дважды это дает значение, и дважды это дает Null.

Роб Фарли
источник