ANSI и не ANSI SQL JOIN синтаксис
У меня есть моя бизнес-логика в ~ 7000 строк хранимых процедур T-SQL, и у большинства из них следующий синтаксис JOIN:
SELECT A.A, B.B, C.C
FROM aaa AS A, bbb AS B, ccc AS C
WHERE
A.B = B.ID
AND B.C = C.ID
AND C.ID = @param
Я получу рост производительности, если я заменил такой запрос следующим:
SELECT A.A, B.B, C.C
FROM aaa AS A
JOIN bbb AS B
ON A.B = B.ID
JOIN ccc AS C
ON B.C = C.ID
AND C.ID = @param
Или они одинаковы?
Ответы
Ответ 1
Два запроса одинаковы, кроме второго - синтаксис SQL ANSI-92, а первый - старший синтаксис SQL, который не включает предложение join. Они должны составить точно такой же внутренний план запросов, хотя вы можете проверить его.
Вы должны использовать синтаксис ANSI-92 по нескольким причинам.
- Использование предложения JOIN разделяет
логика отношений с
(ГДЕ) и, таким образом,
чище и понятнее.
- Это не имеет значения с этим конкретным запросом, но есть несколько обстоятельств, когда более старый внешний синтаксис соединения (с использованием +) неоднозначен, и результаты запроса, следовательно, зависят от реализации - или запрос не может быть разрешен вообще. Это не происходит с ANSI-92
- Это хорошая практика, так как большинство разработчиков и dba будут использовать ANSI-92 в настоящее время, и вы должны следовать стандарту. Конечно, все современные инструменты запросов будут генерировать ANSI-92.
- Как указано в @gbn, он имеет тенденцию избегать случайных кросс-соединений.
Я сам некоторое время сопротивлялся ANSI-92, так как есть небольшое концептуальное преимущество перед старым синтаксисом, поскольку проще предусмотреть SQL как массовое декартово соединение всех используемых таблиц, за которым следует операция фильтрации - умственная техника, которая может быть полезно для понимания того, что делает SQL-запрос. Однако несколько лет назад я решил, что мне нужно двигаться со временем, и после относительно короткого периода корректировки я теперь предпочитаю его - преимущественно из-за первой причины, указанной выше. Единственное место, которое нужно отходить от синтаксиса ANSI-92, или, скорее, не использовать этот параметр, - это естественные объединения, которые неявно опасны.
Ответ 2
Вторая конструкция известна как "синтаксис смешанного соединения" в сообществе SQL. Первая конструкция AFAIK не имеет широко распространенного имени, поэтому назовите ее синтаксисом внутреннего соединения "старый стиль".
Обычные аргументы выглядят следующим образом:
Плюсы "традиционного" синтаксиса:
предикаты физически группируются в предложении WHERE
в
любой порядок, который делает запрос в целом, и n-ary отношения, в частности, легче читать и понимать (предложения ON
синтаксиса infixed могут распространять предикаты, поэтому вам нужно искать появление одной таблицы или столбца над визуальное расстояние).
Недостатки синтаксиса "Традиционный": при исключении одного из предикатов "join" отсутствует ошибка синтаксического анализа, и результатом является декартово произведение (известное как CROSS JOIN
в синтаксисе infixed), и такая ошибка может быть сложно обнаружить и отладить. Кроме того, предикаты "join" и предикаты "фильтрации" физически группируются в предложении WHERE
, что может привести к их смущению друг от друга.
Ответ 3
Выполните оба и проверьте свои планы запросов. Они должны быть равными.
Ответ 4
Два запроса равны - первый использует синтаксис ANSI JOIN, второй - синтаксис ANSI JOIN. Я рекомендую придерживаться синтаксиса ANSI JOIN.
И да, LEFT OUTER JOINs (которые, кстати, также являются синтаксисом ANSI JOIN) - это то, что вы хотите использовать, когда есть вероятность, что таблица, в которую вы присоединяетесь, может не содержать соответствующих записей.
Ссылка: Условные соединения в SQL Server
Ответ 5
ОК, они выполняют то же самое. Это согласилось.
В отличие от многих, я использую более старую конвенцию. То, что SQL-92 "легче понять", является спорным. Записав языки программирования для 40 лет (gulp), я знаю, что "легко читаемый" начинается сначала перед любым другим соглашением с "остротой зрения" (здесь используется неверный термин, но это лучшая фраза, которую я могу использовать).
При чтении SQL ПЕРВАЯ вещь, о которой вы беспокоитесь, касается того, какие таблицы задействованы, а затем какая таблица (большинство) определяет зерно. Затем вы заботитесь о соответствующих ограничениях на данные, а затем выбранные атрибуты. В то время как SQL-92 в основном отделяет эти идеи, существует так много шумовых слов, мозг должен интерпретировать и обрабатывать их, и это делает чтение SQL медленнее.
SELECT Mgt.attrib_a AS attrib_a
,Sta.attrib_b AS attrib_b
,Stb.attrib_c AS attrib_c
FROM Main_Grain_Table Mgt
,Surrounding_TabA Sta
,Surrounding_tabB Stb
WHERE Mgt.sta_join_col = Sta.sta_join_col
AND Mgt.stb_join_col = Stb.stb_join_col
AND Mgt.bus_logic_col = 'TIGHT'
Острота зрения!
Поместите запятые для новых атрибутов впереди. Он также упрощает код комментирования.
Используйте конкретный случай для функций и ключевых слов
Используйте конкретный случай для таблиц
Использовать конкретный случай для атрибутов
Вертикально Выстраивать операторы и операции
Сделать первую таблицу в FROM представляют зернистость данных
Сделайте первые таблицы WHERE равными ограничениям объединения, и пусть конкретные, жесткие ограничения будут плавать в нижней части.
Выберите 3 символа псевдонима для ВСЕХ таблиц в вашей базе данных и используйте псевдоним КАЖДЫЙ, с которым вы ссылаетесь на таблицу. Вы должны использовать этот псевдоним в качестве префикса для (многих) индексов на этой таблице.
6 из 1 1/2 десятка другого, не так ли? Может быть. Но даже если вы используете соглашение ANSI-92 (как и я, и в случае продолжения работы), используйте принципы остроты остроты зрения, выравнивание по вертикали, чтобы ваш мысленный взгляд мог не попасть в места, которые вы хотите видеть, и легко избегать вещей (особенно шумовые слова) вам не нужно.
Ответ 6
В моем представлении предложение FROM - это то, где я решаю, какие столбцы мне нужны в строках для моего предложения SELECT. Здесь выражается бизнес-правило, которое выводит на ту же строку, значения, необходимые в вычислениях. Бизнес-правило может быть клиентом, у которого есть счета-фактуры, в результате чего строятся счета-фактуры, включая ответственность клиента. Это также могут быть места в том же почтовом индексе, что и клиенты, в результате чего список мест и клиентов, которые находятся близко друг к другу.
Здесь я определяю центричность строк в моем результирующем наборе. В конце концов, нам просто показана метафора списка в РСУБД, причем в каждом списке есть тема (сущность), и каждая строка является экземпляром объекта. Если понимать центричность строк, понимается объект набора результатов.
Предложение WHERE, которое концептуально выполняется после строк, определено в предложении from, отбирает строки, которые не требуются (или содержат строки, которые требуются) для предложения SELECT для работы.
Поскольку логика соединения может быть выражена как в предложении FROM, так и в предложении WHERE, а также потому, что существуют предложения для деления и преодоления сложной логики, я выбираю, чтобы поставить логику соединения, которая включает значения в столбцах в предложении FROM, потому что это по существу выражая бизнес-правило, которое поддерживается сопоставлением значений в столбцах.
то есть. Я не буду писать предложение WHERE следующим образом:
WHERE Column1 = Column2
Я поставлю это в предложение FROM следующим образом:
ON Column1 = Column2
Аналогично, если столбец следует сравнивать с внешними значениями (значениями, которые могут быть или не быть в столбце), например, сравнение почтового индекса с конкретным почтовым индексом, я поставлю это в предложение WHERE, потому что я в основном говорю Мне нужны только такие строки.
то есть. Я не буду писать предложение FROM следующим образом:
ON PostCode = '1234'
Я поставлю это в предложение WHERE следующим образом:
WHERE PostCode = '1234'
Ответ 7
Синтаксис ANSI не применяет ни предикативное размещение в правильном предложении (будь то ON или WHERE), ни близость предложения ON к смежной таблице. Разработчик может свободно писать беспорядок
SELECT
C.FullName,
C.CustomerCode,
O.OrderDate,
O.OrderTotal,
OD.ExtendedShippingNotes
FROM
Customer C
CROSS JOIN Order O
INNER JOIN OrderDetail OD
ON C.CustomerID = O.CustomerID
AND C.CustomerStatus = 'Preferred'
AND O.OrderTotal > 1000.0
WHERE
O.OrderID = OD.OrderID;
Говоря о инструментах запросов, которые "будут генерировать ANSI-92", я комментирую здесь, потому что он сгенерировал
SELECT 1
FROM DEPARTMENTS C
JOIN EMPLOYEES A
JOIN JOBS B
ON C.DEPARTMENT_ID = A.DEPARTMENT_ID
ON A.JOB_ID = B.JOB_ID
Единственным синтаксисом, который избегает обычного "файла с ограничением-проектом-декартово", является внешнее соединение. Эта операция сложнее, потому что она не ассоциативна (как с самим собой, так и с нормальным соединением). Нужно, по крайней мере, разумно заключить в круг запрос с внешним соединением. Однако это экзотическая операция; если вы слишком часто используете его, я предлагаю использовать класс реляционных баз данных.