我是 SQL Server 的新手。我最近了解到执行顺序是:
From
Where
Group By
Having
Select
Order By
相关子查询和交叉应用在执行顺序中的位置是什么?
我有一个查询,其中我在 select 子句中关联了子查询。没有 where 子句的外部查询返回 10k 行,应用 where 子句后,它返回 50 行。当外部查询有 where 子句时,相关子查询是执行 10k 次还是 50 次?
根据执行的逻辑顺序,它应该只执行 50 次,因为 select 语句是最后执行的语句之一。但是我的朋友说它执行了 10k 次,因为优化器在“From”逻辑执行顺序期间执行了这个。有什么想法吗?
关系模型的一个新特性是将数据(表、查询)的逻辑表示与物理(磁盘文件、运行时执行)分离。您提供的列表是查询子句的逻辑顺序。它不代表运行时引擎执行的物理顺序。
DBMS 中有一个组件称为查询优化器 (QO)。它的工作是将所需输出(即 SQL 查询)的逻辑定义转换为合理有效的物理实现。可以自由地将查询的各个部分重新排列成任何可证明等效的配置。
例如,如果查询具有 ORDER BY,则 QO 可能决定在执行结束时执行排序。或者,在开始时,它可以读取由于索引而已知处于所需顺序的数据。两个非常不同的物理实现,它们给出了相同的逻辑结果。
选择物理实现的过程称为查询计划。这是一个深刻而引人入胜的话题。现在大多数 DBMS 使用基于成本的优化器。生成备选计划列表,根据一些内部专有成本函数评估每个计划的成本,并选择最便宜的计划执行查询。SQL Server 的优化器基于 Cascades 框架。网上有很多资源可以解释它。
要回答您的实际问题,逻辑上的子查询通常适合它们编写的 SQL 的任何部分。如果它们嵌入在 FROM (
..from T1 inner join (select x from t2) as y..
) 中,则它们被视为 FROM 的一部分。如果在 SELECT (select a, (select b from c where d='e') as f, g, h..
) 中,它们是 SELECT 的一部分。然而,在物理上,它们会在优化器认为最好的地方进行评估。“相关子查询是执行了 10k 次还是 50 次”——可能是其中之一,也可能不是。它可以执行一次并在运行时缓存。这将取决于精确的 SQL、表定义、每个表中涉及的行数、在编译时和运行时设置的选项。如果您想要完整的解释,请提出一个新问题,其中包括所有表、索引和约束的定义。将实际执行计划复制到https://www.brentozar.com/pastetheplan/。DBA.SE 上有很多常客可以解释这意味着什么。
子查询确实提出了额外的优化挑战。Mostafa Elhemali 等人有一篇论文“SQL 子查询的执行策略”,我发现它很有趣且易读。