SQL Server-ANSI JOIN与非ANSI 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

还是一样?

abatishchev asked 2019-11-08T00:56:27Z
7个解决方案
76 votes

这两个查询是相同的,除了第二个查询是ANSI-92 SQL语法,而第一个查询是未合并join子句的较旧的SQL语法。 尽管您可能想检查一下,但它们应该产生完全相同的内部查询计划。

出于多种原因,您应该使用ANSI-92语法

  • JOIN子句的使用将关系逻辑过滤逻辑(WHERE),因此更干净,更容易理解。
  • 这个特定的查询无关紧要,但是在某些情况下,较旧的外部联接语法(使用+)含糊不清,因此查询结果取决于实现-或根本无法解析该查询。 这些在ANSI-92中不会发生
  • 这是一个好习惯,因为大多数开发人员和dba如今将使用ANSI-92,因此您应该遵循该标准。 当然,所有现代查询工具都会生成ANSI-92。
  • 正如@gbn指出的那样,它确实倾向于避免意外的交叉连接。

我本人抵制ANSI-92一段时间,因为旧语法有一点概念上的优势,因为将SQL设想为对所有使用的表进行大规模笛卡尔联接,然后进行过滤操作会更容易-这是一种有用的思维方法 掌握SQL查询的功能。 但是,几年前,我决定需要与时俱进,经过一段较短的调整期后,我现在非常喜欢它-主要是因为上面提到的第一个原因。 唯一应该脱离ANSI-92语法或者不使用该选项的地方是自然连接,这是隐式的危险。

Cruachan answered 2019-11-08T00:57:18Z
4 votes

第二种构造在SQL社区中称为“固定连接语法”。 第一个构造AFAIK没有广泛接受的名称,因此我们将其称为“旧样式”内部联接语法。

通常的参数如下:

“传统”语法的优点:谓词在以下内容的CROSS JOIN子句中进行了物理分组:无论哪种顺序通常会使查询变得更容易理解,尤其是n元关系(固定语法的WHERE子句会分散谓词,因此您必须在可视范围内查找一个表或列的外观 )。

“传统”语法的缺点:省略“ join”谓词之一时没有解析错误,结果是笛卡尔乘积(在固定语法中称为CROSS JOIN),这种错误很难检测和调试。 。 同样,“ join”谓词和“ filtering”谓词在WHERE子句中物理分组在一起,这可能导致它们彼此混淆。

onedaywhen answered 2019-11-08T00:58:03Z
4 votes

好,他们执行相同。 同意了与许多其他约定不同,我使用了较旧的约定。 SQL-92的“易于理解”值得商bat。 我已经写了将近40年的编程语言(大嘴),我知道“易读”首先要以“视觉敏锐度”(在这里用错了术语,但这是我可以使用的最好的短语),然后再以任何其他约定开始。在阅读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个字符的别名,并在引用该表的所有位置使用别名。 您还应该使用该别名作为该表上(许多)索引的前缀。1 1/2打中的6打,对吗? 也许。 但是,即使您使用的是ANSI-92约定(按照我的经验并且在某些情况下会继续使用),也要使用视敏度原理,通过垂直对齐可以使您的视线避开您想看的地方,并轻松避开事物(尤其是 杂音),您不需要。

TwoEdgedSword answered 2019-11-08T00:58:37Z
3 votes

都执行并检查其查询计划。 他们应该是平等的。

sisve answered 2019-11-08T00:59:00Z
3 votes

这两个查询相等-第一个查询使用非ANSI JOIN语法,第二个查询使用ANSI JOIN语法。 我建议坚持使用ANSI JOIN语法。

是的,当要连接的表有可能不包含任何匹配记录时,就想使用LEFT OUTER JOIN(btw也是ANSI JOIN语法)。

参考:SQL Server中的条件联接

OMG Ponies answered 2019-11-08T00:59:37Z
1 votes

我认为FROM子句是决定SELECT子句在行中需要哪些列的地方。 在此表达业务规则的地方将把计算所需的值带到同一行。 业务规则可以是拥有发票的客户,从而导致发票行包括负责的客户。 也可能是与客户使用相同邮政编码的场馆,从而产生了彼此靠近的场馆和客户的列表。

在这里,我可以计算出结果集中各行的中心性。 毕竟,我们只是简单地看到了RDBMS中一个列表的隐喻,每个列表都有一个主题(实体),而每一行都是该实体的实例。 如果了解行中心性,则了解结果集的实体。

WHERE子句在概念上在from子句中定义行之后执行,它会剔除SELECT子句可以使用的不需要的行(或包括必需的行)。

因为可以在FROM子句和WHERE子句中表达联接逻辑,并且因为存在这些子句以划分和征服复杂的逻辑,所以我选择将涉及值的联接逻辑放在FROM子句的列中,因为这实际上是在表达业务 匹配列中的值所支持的规则。

即,我不会像这样编写WHERE子句:

 WHERE Column1 = Column2

我将其放在FROM子句中,如下所示:

 ON Column1 = Column2

同样,如果要将一列与外部值(可能在列中或不在列中的值)进行比较(例如将邮政编码与特定的邮政编码进行比较),我将其放在WHERE子句中,因为我实质上是在说我只想要 这样的行。

即我不会写这样的FROM子句:

 ON PostCode = '1234'

我将其放在WHERE子句中,如下所示:

 WHERE PostCode = '1234'
John answered 2019-11-08T01:00:55Z
0 votes

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

摆脱常规“限制项目-笛卡尔积”的唯一语法是外部联接。 此操作更复杂,因为它不关联(既不关联,也不关联)。 至少必须明智地用外部联接将查询括起来。 但是,这是一个奇特的操作。 如果您经常使用它,建议您使用关系数据库类。

Tegiri Nenashi answered 2019-11-08T01:01:33Z
translate from https://stackoverflow.com:/questions/1599050/will-ansi-join-vs-non-ansi-join-queries-perform-differently