我们需要第一个表的结果(当连接其他表时)在连接(这个问题的内部连接)之前尽可能小,以使我们的查询更快一点。
例如,应该这样:
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 中,表较小,则 SQL 引擎在形成笛卡尔积时要做的工作较少。然后,当您到达 where 语句时,您将在内存中从中筛选出一个缩减的结果集。
我可能离题太远了,这是不真实的。就像我说的,这是一个理论。
你的意见?
注意:我只是刚刚想到这个问题,还没有机会自己进行任何测试。
注 2:标记为 SQL Server,因为我对 MySql 等的实现一无所知。无论如何请随时回答/评论
查询的逻辑处理在MSDN上(由 Microsoft SQL Server 团队编写,而不是第 3 方)
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 是基于成本的,对于复杂的查询,可能需要 2 周才能生成理想的计划。所以它确实“足够好”,但实际上并非如此。
因此,您的第一个案例可能有助于优化器找到更好的计划,因为这两个查询的逻辑处理顺序不同。但它可能不会。
我在 SQL Server 2000 上使用了这个技巧,使报告查询的速度提高了 60 倍。随着 QO 逐个改进版本,它会更好地解决这些问题。