我读了这篇文章: SELECT语句的逻辑处理顺序
在文章的最后已经写过ON和JOIN子句在WHERE之前考虑.
考虑一下我们有一个拥有10百万记录的主表和一个具有50百万记录的详细信息表(引用主表(FK)).我们有一个查询根据主表中的PK只有100条详细记录表.
在这种情况下,ON和JOIN在WHERE之前执行吗?我的意思是我们在JOIN之后有500百万条记录然后WHERE适用于它吗?或者首先应用WHERE然后JOIN和ON考虑?如果第二个答案是真的那么它与top无关文章?
谢谢
Cad*_*oux 23
在内部连接的情况下或在左左边一个表连接,在许多情况下,优化会发现,这是更好地在实际执行任何类型的物理的连接前先进行任何过滤(最高选择性) - 所以有显然是更好的物理运作顺序.
在某种程度上,您有时可以使用SQL来控制(或干扰此),例如,使用子查询中的聚合.
处理查询中的约束的逻辑顺序只能根据已知的不变变换进行变换.
所以:
SELECT *
FROM a
INNER JOIN b
ON a.id = b.id
WHERE a.something = something
AND b.something = something
Run Code Online (Sandbox Code Playgroud)
在逻辑上仍相当于:
SELECT *
FROM a
INNER JOIN b
ON a.id = b.id
AND a.something = something
AND b.something = something
Run Code Online (Sandbox Code Playgroud)
他们通常会有相同的执行计划.
另一方面:
SELECT *
FROM a
LEFT JOIN b
ON a.id = b.id
WHERE a.something = something
AND b.something = something
Run Code Online (Sandbox Code Playgroud)
不等同于:
SELECT *
FROM a
LEFT JOIN b
ON a.id = b.id
AND a.something = something
AND b.something = something
Run Code Online (Sandbox Code Playgroud)
因此优化器不会将它们转换为相同的执行计划.
优化器非常智能,能够非常成功地移动事物,包括折叠视图和内联表值函数,甚至可以相当成功地通过某些类型的聚合来推送.
通常,在编写SQL时,它需要是可理解的,可维护的和正确的.就执行效率而言,如果优化器难以将声明性SQL转换为具有可接受性能的执行计划,则有时可以简化代码或将适当的索引或提示添加或分解为应该执行得更快的步骤- 全部在连续的侵入性命令.
gbn*_*gbn 21
没关系
始终遵循逻辑处理顺序:无论实际处理顺序如何
INNER JOIN和WHERE条件是有效关联和可交换的(因此ANSI-89"加入where"语法)所以实际顺序无关紧要
对于外连接和更复杂的查询,逻辑顺序变得很重要:在OUTER表上应用WHERE会完全更改逻辑.
同样,只要通过遵循逻辑处理顺序维护查询语义,优化器如何在内部执行它并不重要.
这里的关键词是"优化者":它完全符合它所说的
只需重新阅读Paul White 在查询优化工具上的优秀系列,并记住这个问题.
可以使用未记录的命令来禁用特定的转换规则,并深入了解所应用的转换.
USE AdventureWorks2008;
/*Disable the rules*/
DBCC RULEOFF ('SELonJN');
DBCC RULEOFF ('BuildSpool');
SELECT P.ProductNumber,
P.ProductID,
I.Quantity
FROM Production.Product P
JOIN Production.ProductInventory I
ON I.ProductID = P.ProductID
WHERE I.ProductID < 3
OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)
您可以看到禁用这两个规则后会执行笛卡尔连接和过滤.

/*Re-enable them*/
DBCC RULEON ('SELonJN');
DBCC RULEON ('BuildSpool');
SELECT P.ProductNumber,
P.ProductID,
I.Quantity
FROM Production.Product P
JOIN Production.ProductInventory I
ON I.ProductID = P.ProductID
WHERE I.ProductID < 3
OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)
启用它们后,谓词将被向下推入索引查找,从而减少连接操作处理的行数.
