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

Предложение WHERE лучше выполнять до IN и JOIN или после

Я прочитал эту статью: Логический порядок обработки инструкции SELECT

в конце статьи было написано ON и предложение JOIN перед WHERE.

Считаем, что у нас есть мастер-таблица, в которой есть 10 milion recored и таблица подробностей (которая ссылается на главную таблицу (FK)) с записью 50 milion. У нас есть запрос, который требует всего 100 записей таблицы подробностей по PK в мастер-таблица.

В этой ситуации ON и JOIN выполняются до WHERE? Я имею в виду, что у нас есть запись 500 milion после JOIN, а затем WHERE применить к ней? или сначала WHERE применяются, а затем JOIN и ON Рассмотрим? Если второй ответ верно, некогерентность с верхней статьей?

спасибо

4b9b3361

Ответ 1

Не важно

Заказ логической обработки всегда соблюдается: независимо от фактического порядка обработки

Условия INNER JOIN и WHERE являются фактически ассоциативными и коммутативными (следовательно, ANSI-89 "присоединяется к синтаксису where" ), поэтому фактический порядок не имеет значения.

Логический порядок становится важным с внешними объединениями и более сложными запросами: применение WHERE в таблице OUTER полностью изменяет логику.

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

И ключевым словом здесь является "оптимизатор": он делает именно то, что он говорит

Ответ 2

В случае INNER JOIN или таблицы слева в LEFT JOIN во многих случаях оптимизатор обнаруживает, что лучше сначала выполнить какую-либо фильтрацию (максимальную избирательность) до фактического выполнения любого типа физического соединения - так что, очевидно, существует физический порядок операций.

В какой-то мере вы иногда можете контролировать это (или вмешиваться в это) со своим SQL, например, с агрегатами в подзапросах.

Логический порядок обработки ограничений в запросе может быть преобразован только в соответствии с известными инвариантными преобразованиями.

Итак:

SELECT *
FROM a
INNER JOIN b
    ON a.id = b.id
WHERE a.something = something
    AND b.something = something

по-прежнему логически эквивалентен:

SELECT *
FROM a
INNER JOIN b
    ON a.id = b.id
    AND a.something = something
    AND b.something = something

и они, как правило, имеют один и тот же план выполнения.

С другой стороны:

SELECT *
FROM a
LEFT JOIN b
    ON a.id = b.id
WHERE a.something = something
    AND b.something = something

НЕ эквивалентен:

SELECT *
FROM a
LEFT JOIN b
    ON a.id = b.id
    AND a.something = something
    AND b.something = something

и поэтому оптимизатор не собирается преобразовывать их в один и тот же план выполнения.

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

Как правило, при написании SQL он должен быть понятным, удобным и правильным. Что касается эффективности при исполнении, если оптимизатору трудно превратить декларативный SQL в план выполнения с приемлемой производительностью, иногда код может быть упрощен или соответствующие индексы или подсказки добавлены или разбиты на этапы, которые должны выполняться быстрее - все в последовательные порядки инвазивности.

Ответ 3

Просто перечитайте Paul White отличную серию в Оптимизаторе запросов и вспомнили этот вопрос.

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

Для (надеюсь!) очевидных причин попробуйте это только на экземпляре разработки и не забудьте снова включить их и удалить любые субоптимальные планы из кеша.

USE AdventureWorks2008;

/*Disable the rules*/
DBCC RULEOFF ('SELonJN');
DBCC RULEOFF ('BuildSpool');


 SELECT  P.ProductNumber, 
         P.ProductID, 
        I.Quantity
 FROM    Production.Product P
 JOIN    Production.ProductInventory I
         ON  I.ProductID = P.ProductID
WHERE I.ProductID < 3
OPTION (RECOMPILE)

Вы можете видеть, что эти два правила отключены, после чего происходит декартовое объединение и фильтр.

Rules Off Plan

/*Re-enable them*/   
DBCC RULEON ('SELonJN');
DBCC RULEON ('BuildSpool');

 SELECT  P.ProductNumber, 
         P.ProductID, 
        I.Quantity
 FROM    Production.Product P
 JOIN    Production.ProductInventory I
         ON  I.ProductID = P.ProductID
WHERE I.ProductID < 3
OPTION (RECOMPILE)

С их помощью предикат подталкивается прямо в индексный поиск и таким образом уменьшает количество строк, обработанных операцией join.

Rules on Plan

Ответ 4

Нет определенного порядка. Механизм SQL определяет, какой порядок выполнения операций основан на стратегии выполнения, выбранной его оптимизатором.

Ответ 5

Я думаю, что вы неправильно поняли ON как IN в этой статье.

Однако порядок, который он показывает в статье, является правильным (очевидно, это msdn). ON и JOIN выполняются до WHERE естественным образом, потому что WHERE должен применяться как фильтр на временном результирующем наборе, полученном из-за JOINS

В статье говорится, что это логический порядок выполнения, а также в конце абзаца он также добавляет эту строку;)

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