Оптимизировано ли соединение для предложения where во время выполнения?

14

Когда я пишу запрос, как это ...

select *
from table1 t1
join table2 t2
on t1.id = t2.id

Оптимизатор SQL, не уверен, что это правильный термин, переводит это в ...

select *
from table1 t1, table2 t2
where t1.id = t2.id

По сути, является ли оператор Join в SQL Server простым способом написания SQL? Или это на самом деле используется во время выполнения?

Редактировать: я почти всегда и почти всегда буду использовать синтаксис соединения. Мне просто любопытно, что происходит.

Мистер муравей
источник
1
Не могли бы вы остановиться на «почти»? Когда бы вы использовали синтаксис старого стиля и почему?
Аарон Бертран
2
Один крайний случай, когда это действительно имеет значение, если вы добавите (устарело) GROUP BY ALLв
Martin Smith
@MartinSmith кто-нибудь использует GROUP BY ALLнарочно? :-)
Аарон Бертран
@AaronBertrand - я сомневаюсь в этом! Не думаю, что я когда-либо видел, чтобы кто-нибудь использовал это.
Мартин Смит

Ответы:

20

Те рушатся до одного и того же внутри. Первый - это тот, который вы всегда должны писать . Что более важно, почему это важно? Они идентичны с точки зрения плана выполнения и производительности (при условии, что вы не перепутаете это, что легче сделать с помощью ленивого синтаксиса старого стиля).

Вот доказательство использования AdventureWorks, что нет CROSS JOINи filterпроисходит.


Явное соединение:

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


Неявное соединение:

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


Смотри, ма! Идентичные планы, идентичные результаты, никаких перекрестных объединений или фильтров не видно нигде.

(Для ясности, предупреждение об SELECTоператоре в обоих случаях - это неявное преобразование, влияющее на количество элементов, в любом случае это никак не связано с объединением.)

Аарон Бертран
источник
20

Строго говоря, существует разница во входных данных для оптимизатора запросов между двумя формами:

-- Input tree (ISO-89)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM 
    Production.Product AS p,
    Production.ProductInventory AS inv
WHERE
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

Дерево ввода ISO-89

-- Input tree (ISO-92)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM Production.Product AS p
JOIN Production.ProductInventory AS inv ON
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

Дерево ввода ISO-92

Как вы можете видеть, ONпредикат предложения тесно связан с объединением с использованием современного синтаксиса. При более старом синтаксисе существует логическое перекрестное соединение, за которым следует реляционный выбор (фильтр строк).

Оптимизатор запросов почти всегда объединяет реляционный выбор в объединение во время оптимизации, что означает, что две формы, скорее всего, будут создавать эквивалентные планы запросов, но реальной гарантии нет.

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

Для внутреннего соединения они взаимозаменяемы, но для внешних соединений они имеют разные значения - ON соответствует, а WHERE - простая фильтрация. Поэтому лучше придерживаться правильного соответствия синтаксиса JOIN при включении.

DaniSQL
источник
4

ОК, мне было любопытно, поэтому я сделал тест. Я получил реальные планы выполнения для следующего.

select * 
from sys.database_principals prin, sys.database_permissions perm
WHERE prin.principal_id = perm.grantee_principal_id

и

select * 
from sys.database_principals prin
JOIN sys.database_permissions perm
    ON prin.principal_id = perm.grantee_principal_id

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

При этом вам следует использовать JOINсинтаксис, потому что его легче читать, и вы с меньшей вероятностью допускаете ошибки, особенно в сложных запросах. И синтаксис *=/ =*для OUTERобъединений уже удален с SQL-Server 2005.

Кеннет Фишер
источник