SQL Server联接/位置处理顺序


18

在阅读了慢速SQL查询之后,不确定如何优化,这让我开始思考查询的一般性能。当然,我们需要将第一个表(在连接其他表时)的结果尽可能小,然后再进行连接(此问题的内部连接),以使我们的查询快一点。

示例,应该这样:

SELECT *
FROM   ( SELECT * FROM table1 WHERE col = @val ) t
INNER JOIN table2 ON col = col2

比以下更好/更快:

SELECT *
FROM table1
INNER JOIN table2 ON col = col2
WHERE table1.col = @val

我的理论如下(这可能不是正确的实现,我试图从我读过的一本SQL Server 2008内部书籍(MSFT Press)中记住):

  1. 查询处理器首先获取左表(表1)
  2. 在过滤掉必要的行之前,连接第二个表(表2)并形成笛卡尔积(如果适用)
  3. 然后使用SEELCT语句最后执行WHERE,ORDER BY,GROUP BY,HAVING子句。

因此,如果在上面的语句1中表较小,则在形成笛卡尔积时SQL引擎要做的工作较少。然后,当您到达where语句时,您将得到减少的结果集,可以从中筛选出结果集。

我可能还差得远,这是不真实的。就像我说的,这是一种理论。

你的想法?

注意:我只是想到了这个问题,还没有机会自己进行任何测试。

注2:标记为SQL Server的,因为我不知道任何关于MySQL等的实施,请随时接听/评论反正

Answers:


15

查询的逻辑处理是在MSDN上(由Microsoft SQL Server团队编写,而不是由第三方编写)

1. FROM
2. ON
3. JOIN
4. WHERE
5. GROUP BY
6. WITH CUBE or WITH ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10. ORDER BY
11. TOP

派生表跟随此操作,然后外部查询再次执行此操作等

但这是合乎逻辑的:不是实际的。不管SQL Server实际如何执行,这些语义都应遵循这封信。“实际”由查询优化器(QO)确定,并且避免使用提到的中间Cartesion产品。

值得一提的是,SQL是声明性的:您说的是“什么”而不是“如何”,就像过程/命令式编程(Java,.net)一样。因此,在许多情况下,说“在此之前发生”是错误的(例如,假设发生短路或L-to-R WHERE顺序)

在上述情况下,由于QO是简单的查询,因此无论其结构如何,QO都会生成相同的计划。

但是,QO是基于成本的,对于复杂的查询,可能需要2周才能生成理想的计划。所以它做的“足够好”,实际上不是。

因此,您的第一种情况可能会帮助优化器找到更好的计划,因为这两个查询的逻辑处理顺序是不同的。但事实并非如此。

我已在SQL Server 2000上使用此技巧,以使报告查询的速度性能提高60倍。随着QO的版本升级,在解决这些问题上会变得更好。

您提到的书:对此有一些争议。
请参阅SO及其后续链接:https : //stackoverflow.com/q/3270338/27535


6

SQL查询本质上不是过程性的,没有联接运算符的自上而下的处理。示例查询中表的顺序对执行计划没有影响,因为它们在逻辑上是等效的,并且将生成完全相同的计划。

您已经评估了查询优化器为该查询生成计划时可能考虑的两个选项。影响计划选择的主要因素是所涉及表的统计信息以及与任何候选计划中的操作员选择相关的成本

数百个不同的执行计划中的任何一个都可以满足一个非常简单的两表联接(例如您的示例)。优化人员通过比较这些计划的成本来决定哪种方法是回答您的查询的最佳方法。

它有时会出错,您可以通过改进索引编制,保持统计信息更新和应用提示来帮助它做出更好的选择。在极少数情况下,您可能想通过使用FORCE ORDER提示来强制执行顺序,但应谨慎使用。用锤子敲碎螺母,通常可以通过向优化器提供更好的信息来使其产生更好的计划。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.