#sql #sql-server #sql-execution-plan
Вопрос:
Из SELECT
документов SQLServer:
Следующие шаги показывают логический порядок обработки или порядок привязки для инструкции SELECT. Этот порядок определяет, когда объекты, определенные на одном шаге, становятся доступными для предложений на последующих шагах. Например, если обработчик запросов может привязываться (получать доступ) к таблицам или представлениям, определенным в предложении FROM, эти объекты и их столбцы становятся доступными для всех последующих шагов.
- От
- НА
- Присоединиться
Мой вопрос в том, в чем разница между ON
и JOIN
в плане выполнения? Например, если запрос представляет собой что-то вроде:
SELECT *
FROM person JOIN county ON person.nationality=country.code
Я бы понял, что первым шагом будет проверка привилегий для FROM
таблицы (таблиц):
- Имеет ли пользователь доступ к таблицам
person
иcountry
?
Но тогда, если, например, для объединения двух таблиц выполняется соединение с вложенным циклом, в чем разница между ON
и JOIN
? И, исходя из этого различия, почему ON
необходимость должна предшествовать JOIN
?
Я полагаю, единственное, о чем я могу думать, это сначала проверить ON
предложение, чтобы убедиться, что соединение имеет смысл. Два примера могут быть:
SELECT *
FROM person JOIN county ON 1=0 -- never need to do the join
И:
SELECT *
FROM person JOIN county ON person.badcolumn = country.code
Ответ №1:
Я думаю, вы неправильно понимаете, о чем идет речь в этом документе:
Я бы понял, что первым шагом будет проверка привилегий для таблиц FROM
Это не то, что он говорит, это не относится к разрешениям пользователя. Это относится к тому, как каждая часть запроса может ссылаться на логически предыдущие части запроса, но не на более поздние части, и объясняет, почему на SELECT
него нельзя ссылаться, даже если он написан ранее в запросе. Это ограничение времени компиляции при построении запроса, а не ограничение времени выполнения.
В таком запросе, как этот:
SELECT *
FROM person p
JOIN county c ON p.nationality = c.code
- Сначала
FROM
вычисляется и не может ссылаться на какую-либо другую часть запроса.
Например, вы не можете этого сделать
SELECT *
FROM OPENJSON(p.JsonColumn)
CROSS JOIN person p
Это должно быть в обратном порядке
SELECT *
FROM person p
CROSS APPLY OPENJSON(p.JsonColumn)
ON
Предложение идет дальше, доJOIN
, неясно, в чем разница, как вы говорите. Я полагаю, что это просто относится к вложенному предложению join, такому как приведенное ниже
SELECT *
FROM person p
JOIN county c
JOIN state s ON c.state_id = s.state_id
ON p.nationality = c.code
Это может быть небольшим заблуждением со стороны Microsoft, поскольку в этом случае вложенное соединение не может ссылаться ни на какую часть запроса, даже на FROM
- Далее
JOIN
идут s иAPPLY
s, и каждый может ссылаться на предыдущий в строго текстовом порядке.
если, например, выполняется объединение вложенного цикла для объединения двух таблиц
Тип соединения, выполняемого компилятором, не имеет отношения к этому вопросу.
сначала он проверит предложение ON, чтобы убедиться, что соединение имеет смысл
Нет, это чисто семантика времени выполнения. Вы можете присоединиться к любому условию, которое вы можете создать, даже если во время выполнения известно, что оно не создает строк. Компилятор может оптимизировать его, но это разрешено.