SQL Server 2005 - 内部联接的顺序

Posted

技术标签:

【中文标题】SQL Server 2005 - 内部联接的顺序【英文标题】:SQL Server 2005 - Order of Inner Joins 【发布时间】:2010-11-23 00:37:02 【问题描述】:

我在 Where 子句中有一个包含三个内部连接语句的查询。执行查询大约需要 2 分钟。如果我只是改变两个内部连接的顺序,性能下降到 40 秒。

除了改变内部连接的顺序之外什么都不做怎么会对查询性能产生如此巨大的影响呢?我原以为优化器会解决所有这些问题。

【问题讨论】:

它应该正常。你是否不止一次地同时测试它?你能发布两个版本吗? 【参考方案1】:

SQL 是声明性的,即 JOIN 顺序无关紧要。

但在实践中,如果优化器没有探索所有选项(理论上可能需要几个月),这是一个复杂的查询。

另一种选择是,如果您重新排序并获得不同的结果,这是一个非常不同的查询,但这通常是使用 OUTER JOIN。

它也可能是指定 ON 子句的方式 如果您重新排序 FROM 子句,它必须更改。除非您使用的是旧的(并且不好的)JOIN-in-the-WHERE-clause。

最后,如果担心,您可以使用括号更改评估顺序以明确您的意图,例如,首先过滤大表以生成派生表。

【讨论】:

【参考方案2】:

我本以为这样做也足够聪明,但显然它仍然按照您明确列出它们的顺序执行连接...至于为什么会影响性能,如果第一个连接产生中间结果在一个排序方案中仅包含 100 条记录,那么第二个连接将从该 100 条记录集到第三个表。 如果将另一个联接首先生成一百万条记录的第一个中间结果集,那么第二个联接将从一百万行结果集到第三个表...

【讨论】:

查询计划通常会以最佳方式重新排序连接,但它有一个超时时间,可以在此时间内优化查询。如果查询非常复杂,它实际上会放弃并使用迄今为止找到的最佳计划。如果单击“显示执行计划 XML”,您将看到 StatementOptmEarlyAbortReason="TimeOut"【参考方案3】:

因为通过更改联接的顺序,SQL Server 为您的查询提出了不同的执行计划(它可能会改变它根据您的联接过滤表的方式)。

在这种情况下,我猜您有几个大表...其中一个执行大部分过滤。

在一个查询中,您的联接将几个大表联接在一起,然后在最后过滤记录。

另一方面,您将第一个表过滤到一个更小的数据子集...然后将其余表加入其中。由于该初始表在加入其他大型记录集之前已被过滤,性能要好得多。

您始终可以验证但在启用“显示查询计划”选项的情况下运行查询,并查看两个不同连接顺序的查询计划。

【讨论】:

以上是关于SQL Server 2005 - 内部联接的顺序的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server-交叉联接内部联接基础回顾

带有内部联接的 SQL Server 更新

基于 SQL Server 2008 中列值的内部联接

SQL Server 中使用 Sum Aggregate 函数进行内部联接

带有 2 个内部联接的 SQL Server 2014 STUFF

我可以将 PIVOT 与 Microsoft SQL Server 中的内部联接结合起来吗?