Вопрос по плану запроса. Nested Loops возвращает лишние строки

Андрей_Батькович
Дата: 05.05.2015 22:21:32
Привет всем!

Вопрос по плану запроса.
Есть запрос с соединением 3х таблиц:

SELECT TOP 100
CASE
WHEN T1._Fld777_TYPE = 0x08 AND T1._Fld777_RTRef = @P1
THEN T2._Code
WHEN T1._Fld777_TYPE = 0x08 AND T1._Fld777_RTRef = @P2
THEN T3._Code
ELSE CAST(NULL AS NVARCHAR(9))
END
FROM _InfoRg750 T1 WITH(NOLOCK)
LEFT OUTER JOIN _Reference7 T2 WITH(NOLOCK)
ON T1._Fld777_TYPE = 0x08 AND T1._Fld777_RTRef = @P3
AND T1._Fld777_RRRef = T2._IDRRef
LEFT OUTER JOIN _Reference11 T3 WITH(NOLOCK)
ON T1._Fld777_TYPE = 0x08 AND T1._Fld777_RTRef = @P4
AND T1._Fld777_RRRef = T3._IDRRef

Запрос выполняется из 1С. Текст запроса с параметрами есть в приложении.
При выполнении соединения с таблицей Reference11 выбирается план с Nested Loops. В ведущей таблице 100 строк, ведомой таблицей является Reference11 и в ней всего 4 записи. Следовательно Reference11 внутри цикла опрашивается 100 раз, но вот чего я не понимаю почему при этом возвращается 400 строк?

Ведь в таблице всего 4 строки, зачем нужно возвращать 400?

Ссылка на базу, план запроса и текст запроса для воспроизведения находятся во вложении.

Заранее большое спасибо за ответы.
invm
Дата: 05.05.2015 23:06:45
Это кумулятивное значение - общее число строк, которое вернул оператор: 100 раз по 4 строки = 400
Андрей_Батькович
Дата: 06.05.2015 00:08:55
invm,

Это я понимаю, я не понимаю зачем он это сделал.
invm
Дата: 06.05.2015 00:11:24
Кто "он" и что "это"?
Андрей_Батькович
Дата: 06.05.2015 00:15:15
invm,

Он - оптимизатор
Это - зачем возвращать 400 строк когда можно 1 раз вернуть 4 строки.
invm
Дата: 06.05.2015 00:37:36
Андрей_Батькович
можно 1 раз вернуть 4 строки.
Вернуть куда? Вы представляете как работает NL?
Андрей_Батькович
Дата: 06.05.2015 01:40:53
invm,

То что NL выполняет оператор скана таблицы 100 раз это все понятно, тут вопросов нет.
Вопрос по фактическому количеству строк.

Насколько я знаю фактическое количество строк, это то количество которое удовлетворяет условию, в данном случае условию соединения. Может быть это не всегда так?

При соединении со справочником _Reference11 условию удовлетворяет всего 1 строка, она выводится под номером 29 в результате запроса.
Так почему тогда фактическое количество строк равно 400 а не 1?
Mind
Дата: 06.05.2015 02:41:25
Андрей_Батькович
Насколько я знаю фактическое количество строк, это то количество которое удовлетворяет условию, в данном случае условию соединения. Может быть это не всегда так?
Нет.

Андрей_Батькович
При соединении со справочником _Reference11 условию удовлетворяет всего 1 строка, она выводится под номером 29 в результате запроса.
Вы понимаете что чтобы что-то соединить нужно сначала это что-то прочитать из таблицы? И для каждой строки из внешней таблицы сервер читает все 4 строки из внутренней, потому что используется сканирование индекса, а не поиск по индексу, то есть лишние строки отбрасываются в операторе Nested Loops, а не Clustered Index Scan.
Андрей_Батькович
Так почему тогда фактическое количество строк равно 400 а не 1?
Потому что фактическое количество строк прочитанное оператором Clustered Index Scan и переданное в Nested Loops равно 400 строк. Оптимизатор решил сделать фильтрацию в самом Nested Loops, а не при чтении из таблицы.
Андрей_Батькович
Дата: 06.05.2015 12:03:49
Mind,

Спасибо за ответ.

> Оптимизатор решил сделать фильтрацию в самом Nested Loops, а не при чтении из таблицы.

Понятно, а оптимизатор в принципе умеет фильтровать данные при чтении таблицы, а не в самом NL?
o-o
Дата: 06.05.2015 12:17:52
Андрей_Батькович
а оптимизатор в принципе умеет фильтровать данные при чтении таблицы, а не в самом NL?

конечно умеет.
у меня PK по custid,
и выбираю я orders с конкретным custid,
разумеется, он еще до NL customers отфильтрует: