5

我正在读一本书“在 Microsoft SQL Server 2008 内部:T-SQL 查询*,它通过一个例子说,当首先在两个表之间进行任何连接时,笛卡尔积发生在它们之间,然后它被过滤为 ON 条件,然后通过” RIGHT”、“LEFT”或“FULL”连接类型。

从那本书的一个例子中,

SELECT C.customerid, COUNT(O.orderid) AS numorders
FROM dbo.Customers AS C
LEFT OUTER JOIN dbo.Orders AS O
ON C.customerid = O.customerid

Customer 表有 4 行,Orders 有 7 行。因此,第一个笛卡尔积将生成 4*7 = 28 行,然后将通过“ON”子句和 LEFT OUTER 进行过滤。

这是否意味着无论我使用哪种连接类型,每次笛卡尔积都会在表之间发生?那么为什么我们会看到不同连接之间的性能差异呢?

4

3 回答 3

5

SQL Server当然不会为每个连接计算笛卡尔积然后对其进行过滤,它所做的是将您的SQL语句与左,右,内......您指定的任何连接类型,然后优化器将进行根据表上存在的关于使用什么物理连接运算符的统计信息来决定。

有3个物理运算符:

  • 嵌套循环加入
  • 合并加入
  • 哈希连接

所有 3 都有自己的理想场景,它们最适合使用(我不打算在这里解释它们,每个都有大量文章),它主要取决于连接中涉及的每个表的基数估计和关于优化器期望返回多少行的统计信息,以了解使用了哪一行。

Craig Freedman 有一系列很棒的博客文章,讨论了 SQL Server 中的连接是如何工作的,这些都在这里:

加入 - 克雷格·弗里德曼

我建议查看该列表中底部的 5 篇文章,其中包括对连接的介绍、连接属性的摘要以及每个物理连接运算符的合理深入信息。

于 2013-11-06T14:39:09.120 回答
1

两个表之间的任何连接首先在它们之间发生笛卡尔积,然后使用 ON 条件过滤,然后通过“RIGHT”、“LEFT”或“FULL”连接类型进行过滤。

只是对所做工作的逻辑描述。结果将与此相同,但根据您拥有的索引和表中的数据,它将以不同的方式实现。

查看set showplan on然后进行查询,它将解释如何查找数据。希望这本书能在你深入研究时解释这一点。

于 2013-11-05T20:12:16.673 回答
1

说笛卡尔积发生然后被过滤是非常误导的。如果是这种情况,那么连接 200 万行表几乎是不可能的,因为首先,您将从一万亿行结果集开始,然后对其进行过滤。没有多少 SQL-Server 实现可以处理那个。

因此,不,对于编写良好的查询,笛卡尔积不是该过程的第一步。对于一个写得不好的查询,所有的赌注都被取消了。可以强制 SQL-Server 做出该选择,但这几乎毫无疑问是程序员错误的一个简单示例。

于 2014-06-27T22:35:10.523 回答