两个表之间的连接生成笛卡尔积

7
我正在阅读一本名为“Inside Microsoft SQL Server 2008: T-SQL Querying”的书,其中举例说明在两个表之间进行任何连接时,首先会发生笛卡尔积,然后通过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

客户表有4行,订单表有7行。因此,第一个笛卡尔积将生成4*7=28行,然后将通过"ON"子句和LEFT OUTER进行过滤。

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


抱歉我的英语不好,可能因此我无法清楚地理解那本书的内容。 - Zerotoinfinity
1
尝试使用CROSS JOIN语句。 - Aycan Yaşıt
@Aycan,我没听懂你的意思。我的问题是想了解T-SQL内部的工作原理。 - Zerotoinfinity
1
@AycanYaşıt 我认为OP想知道左连接是否实际上可以被视为稍后过滤的交叉连接,还是它实际上发生在SQL Server内部。 - GSerg
抱歉,我当时没有理解你的问题。 - Aycan Yaşıt
3个回答

7
SQL Server并不会为每个连接计算笛卡尔积然后再进行过滤,它所做的是根据表上存在的统计数据,采用您指定的左、右、内部等连接类型来优化器决策使用哪个物理连接运算符。有三种物理运算符:嵌套循环连接、合并连接和哈希连接。所有三种都有自己的理想情况,在这些情况下最好使用它们(我不会在这里解释它们,因为有大量关于每个运算符的文章),它主要取决于参与连接的每个表的基数估计以及优化器期望返回多少行的统计信息。Craig Freedman有一系列关于SQL Server中连接工作原理的博客文章,全部在这里:Joins - Craig Freedman。我建议查看该列表中的最后5篇文章,其中包括连接介绍、连接属性摘要,以及每个物理连接运算符的相当深入的信息。

+1 我可以看到它比我预期的有更详细的信息。 - Zerotoinfinity
很棒的帖子和精彩的回答 - 正是我所需要的。 - Malik Khalil

2
说笛卡尔积先发生再被过滤是非常误导人的。如果这样的话,那么连接两个拥有200万行的表将几乎不可能,因为首先你会得到1万亿行的结果集然后再进行过滤。很少有SQL-Server实现能够处理那么大的数据量。因此,对于一个良好编写的查询,笛卡尔积不是过程的第一步。对于一个编写不良的查询,情况则未知。虽然可以强制SQL-Server做出这个选择,但这几乎毫无疑问是程序员错误的一个简单例子。

1

在两个表之间进行任何连接时,首先会发生笛卡尔积,然后使用ON条件进行过滤,最后根据“RIGHT”、“LEFT”或“FULL”连接类型进行连接。这只是对所做的事情的逻辑描述。结果将与此相同,但它将根据您拥有的索引和表中的数据而实现不同。

请参见set showplan on,然后执行查询,它将解释如何查找数据。希望随着您深入了解书籍,它会解释这一点。


我做到了。通过阅读它,我推测这是以表格格式呈现的执行计划。如果我理解错误,请纠正我。 - Zerotoinfinity
我认为这是正确的,但是你需要做的主要事情是多在书上学习,然后再回过头来看这个问题,当你学到更多的时候。 - mmmmmm
那确实是正确的选择 :). 不过,我会保持这个选项开放,看看是否能得到更多的回应。无论如何,我会在进展书籍时分享我的发现。 - Zerotoinfinity

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接