Подтвердить что ты не робот

LEFT INNER JOIN против LEFT OUTER JOIN - Почему OUTER занимает больше времени?

У нас есть запрос ниже. Использование соединения LEFT OUTER занимает 9 секунд. Изменение LEFT OUTER на LEFT INNER сокращает время выполнения до 2 секунд, и возвращается число строк одинаковое. Поскольку такое же количество строк из таблицы dbo.Accepts обрабатывается независимо от типа соединения, почему внешний элемент займет 3 раза больше?

SELECT CONVERT(varchar, a.ReadTime, 101) as ReadDate,
       a.SubID,
       a.PlantID,
       a.Unit as UnitID,
       a.SubAssembly,
       m.Lot
  FROM dbo.Accepts a WITH (NOLOCK)
LEFT OUTER Join dbo.Marker m WITH (NOLOCK) ON m.SubID = a.SubID
WHERE a.LastModifiedTime BETWEEN @LastModifiedTimeStart AND @LastModifiedTimeEnd 
  AND a.SubAssembly = '400'
4b9b3361

Ответ 1

Тот факт, что возвращается такое же количество строк, является фактом после того, как оптимизатор запросов не может заранее знать, что каждая строка в Accepts имеет подходящую строку в Marker, не так ли?

Если вы присоединитесь к двум таблицам A и B, скажем, что A имеет 1 миллион строк, а B имеет 1 строку. Если вы говорите, что A LEFT INNER JOIN B означает, что могут появиться только строки, соответствующие и A и B, поэтому план запроса может сначала сканировать B, а затем использовать индекс для сканирования диапазона в A, и, возможно, верните 10 строк. Но если вы скажете A LEFT OUTER JOIN B, то по крайней мере все строки в должны быть возвращены, поэтому план должен сканировать все в независимо от того, что он находит в B. Используя OUTER-соединение, вы устраняете одну возможную оптимизацию.

Если вы знаете, что каждая строка в Accepts будет иметь совпадение с маркером, то почему бы не объявить внешний ключ для обеспечения этого? Оптимизатор увидит ограничение, и если он доверен, учтите его в плане.

Ответ 2

1) в окне запроса в SQL Server Management Studio выполните команду:

SET SHOWPLAN_ALL ON

2) запустите медленный запрос

3) ваш запрос не будет запущен, но план выполнения будет возвращен. сохраните этот вывод

4) запустите свою быструю версию запроса

5) ваш запрос не будет запущен, но план выполнения будет возвращен. сохраните этот вывод

6) сравните вывод медленной версии запроса с выходом версии быстрого запроса.

7), если вы все еще не знаете, почему один медленнее, опубликуйте оба вывода в своем вопросе (отредактируйте его), и кто-то здесь может помочь оттуда.

Ответ 3

Это связано с тем, что LEFT OUTER Join выполняет больше работы, чем INNER Join, перед отправкой результатов.

Inner Join ищет все записи, где оператор ON является истинным (поэтому, когда он создает новую таблицу, он помещает только записи, соответствующие m.SubID = a.SubID). Затем он сравнивает эти результаты с вашим предложением WHERE (ваше последнее измененное время).

The Left Outer Join... принимает все записи в вашей первой таблице. Если оператор ON не является истинным (m.SubID не равен a.SubID), он просто NULLS значения во втором столбце таблицы для этого набора записей.

Причина, по которой вы получаете одинаковое количество результатов в конце, вероятно, является совпадением из-за предложения WHERE, которое происходит ПОСЛЕ всех копий записей.

Join (SQL) Wikipedia

Ответ 4

Подождите - вы на самом деле означали, что "такое же количество строк... обрабатывается " или что "такое же количество строк возвращается"? В общем случае внешнее соединение обрабатывало бы еще много строк, в том числе те, для которых нет совпадения, даже если оно возвращает одинаковое количество записей.