Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server ANSI连接查询与非ANSI连接查询的性能是否会有所不同?_Sql Server_Tsql_Join_Sql - Fatal编程技术网

Sql server ANSI连接查询与非ANSI连接查询的性能是否会有所不同?

Sql server ANSI连接查询与非ANSI连接查询的性能是否会有所不同?,sql-server,tsql,join,sql,Sql Server,Tsql,Join,Sql,我的业务逻辑包含约7000行T-SQL存储过程,其中大多数具有next 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 J

我的业务逻辑包含约7000行T-SQL存储过程,其中大多数具有next 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

或者它们是相同的?

同时执行并检查它们的查询计划。它们应该相等。

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

是的,当您要加入的表可能不包含任何匹配的记录时,您希望使用左外部联接(顺便说一句,左外部联接也是ANSI联接语法)


参考:

这两个查询是相同的,除了第二个是ANSI-92 SQL语法,第一个是旧的SQL语法,它没有包含join子句。它们应该生成完全相同的内部查询计划,尽管您可能希望进行检查

出于以下几个原因,您应该使用ANSI-92语法

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

我本人抵制ANSI-92有一段时间了,因为旧语法在概念上有一点优势,因为它更容易将SQL设想为使用的所有表的大规模笛卡尔连接,然后进行过滤操作——这是一种有助于掌握SQL查询正在做什么的心理技巧。然而,几年前我决定,我需要与时俱进,经过一段相对较短的调整期后,我现在非常喜欢它——主要是因为上面给出的第一个原因。唯一应该偏离ANSI-92语法的地方,或者更确切地说,不使用该选项的地方是使用自然连接,这是隐含的危险。

第二种构造在SQL社区中称为“infixed join syntax”。第一个构造AFAIK没有被广泛接受的名称,所以让我们称之为“旧式”内部连接语法

通常的论点如下:

 WHERE Column1 = Column2
 ON Column1 = Column2
 ON PostCode = '1234'
 WHERE PostCode = '1234'
“传统”语法的优点 谓词在中的
WHERE
子句中进行物理分组 无论查询的顺序如何,尤其是n元关系,都更容易阅读和理解(中缀语法的
ON
子句可以扩展谓词,因此您必须在可视距离上查找一个表或列的外观)


“传统”语法的缺点:省略其中一个“连接”谓词时没有解析错误,结果是笛卡尔积(在中缀语法中称为
交叉连接
),这种错误可能很难检测和调试。此外,'join'谓词和'filtering'谓词在
WHERE
子句中被物理分组在一起,这可能会导致它们相互混淆。

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

摆脱传统“限制项目笛卡尔乘积”的唯一语法是外部联接。此操作更复杂,因为它不关联(与自身和法线联接都不关联)。至少要明智地使用外部联接将查询括起来。然而,这是一种奇特的操作;如果您经常使用它,我建议您使用关系数据库类

在我看来,FROM子句是我决定SELECT子句需要处理的行中的哪些列的地方。它是一个业务规则表达的地方,它将把计算中需要的值带到同一行。业务规则可以是拥有发票的客户,从而生成包括负责客户在内的发票行。它也可以是与客户位于同一邮政编码的场馆,从而生成一个场馆和客户的列表

这是我计算结果集中行的中心度的地方。毕竟,我们只看到RDBMS中列表的隐喻,每个列表都有一个主题(实体),每一行都是实体的一个实例。如果理解行的中心性,则理解结果集的实体

WHERE子句概念上是在from子句中定义行之后执行的,它剔除SELECT子句不需要的行(或包括需要的行)

因为连接逻辑可以在FROM子句和WHERE子句中表示,并且因为子句的存在是为了划分和征服复杂的逻辑,所以我选择将包含FROM子句中列中的值的连接逻辑放在FROM子句中,因为它本质上是表示由列中的匹配值支持的业务规则

i、 e.我不会写这样的WHERE子句:

 WHERE Column1 = Column2
 ON Column1 = Column2
 ON PostCode = '1234'
 WHERE PostCode = '1234'
我会在FROM条款中这样写:

 WHERE Column1 = Column2
 ON Column1 = Column2
 ON PostCode = '1234'
 WHERE PostCode = '1234'
同样,如果要将一列与外部值(可能在列中的值,也可能不在列中的值)进行比较,例如将邮政编码与特定邮政编码进行比较,我会将其放在WHERE子句中,因为我本质上是说我只需要这样的行

i、 e.我不会写这样的FROM条款:

 WHERE Column1 = Column2
 ON Column1 = Column2
 ON PostCode = '1234'
 WHERE PostCode = '1234'
我会在WHERE条款中这样写:

 WHERE Column1 = Column2
 ON Column1 = Column2
 ON PostCode = '1234'
 WHERE PostCode = '1234'

好的,它们执行相同的操作。同意了。 不像很多人,我用的是旧的