【发布时间】:2011-01-16 19:37:36
【问题描述】:
您好,我做了一个 SQL 测试并且对一个问题感到怀疑/好奇:
SQL 引擎执行查询和子查询的顺序是什么?
答案是
- 主查询->子查询->子子查询等
- 子子查询 -> 子查询 -> 主查询
- 一次性解释整个查询
- 没有固定的解释顺序,查询解析器会即时做出决定
我选择了最后一个答案(只是假设它是最可靠的 w.r.t. 其他人)。 现在的好奇心:
我在哪里可以阅读到这方面的信息,简要介绍一下这一切背后的机制是什么?
谢谢。
【问题讨论】:
您好,我做了一个 SQL 测试并且对一个问题感到怀疑/好奇:
SQL 引擎执行查询和子查询的顺序是什么?
答案是
我选择了最后一个答案(只是假设它是最可靠的 w.r.t. 其他人)。 现在的好奇心:
我在哪里可以阅读到这方面的信息,简要介绍一下这一切背后的机制是什么?
谢谢。
【问题讨论】:
这通常取决于您的 DBMS,但是……我认为第二个答案更合理。 没有子查询结果,通常无法计算素数查询。
【讨论】:
SQL 引擎尝试优化(子)查询的执行顺序。决定这一点的部分称为查询优化器。查询优化器知道每个表中有多少行、哪些表有索引以及在哪些字段上。它使用该信息来决定首先执行哪个部分。
【讨论】:
我认为答案 4 是正确的。有几个注意事项:
子查询的类型 - 是否相关。考虑:
SELECT *
FROM t1
WHERE id IN (
SELECT id
FROM t2
)
这里,子查询与外部查询不相关。如果 t2.id 中的值数量比 t1.id 少,那么最有效的方法可能是先执行子查询,并将结果保存在内存中,然后扫描 t1 或 t1.id 上的索引,匹配缓存的值。
但如果查询是:
SELECT *
FROM t1
WHERE id IN (
SELECT id
FROM t2
WHERE t2.type = t1.type
)
这里子查询是相关的——除非 t1.type 已知,否则无法计算子查询。由于 t1.type 的值可能因外部查询的每一行而异,因此该子查询可以针对外部查询的每一行执行一次。
然后,RDBMS 可能真的很聪明,并且意识到 t2.type 只有几个可能的值。在这种情况下,如果它可以猜测执行一次子查询的成本会比为每一行执行一次更便宜,它可能仍然使用用于不相关子查询的方法。
【讨论】:
from t2 我们有 from t2,t1 那么主查询和子查询不相关。我说的对吗?
选项 4 接近。
SQL 是declarative:你告诉查询优化器你想要什么,它会产生最好的(取决于时间/“成本”等)方法。对于外观相同的查询和表,这可能会有所不同,具体取决于统计信息、数据分布、行数、并行度以及天知道还有什么。
这意味着没有固定的顺序。但这并不完全是“即时”
即使使用相同的服务器、架构、查询和数据,我也看到执行计划不同
【讨论】:
如果您想阅读有关这些主题的内容,请获取 Inside SQL Server 2008:T-SQL 查询的副本。它有两章专门介绍如何在 SQL Server 中对查询进行逻辑和物理处理。
【讨论】: