SQL 是否保证子查询中的“SELECT *”将被优化以防止完全扫描?

var*_*ble 3 sql-server sql-server-2019

我正在探索扩展事件查询跟踪,并对几个奇怪的查询有疑问,如下所示:

示例1:

select top 10  *   from   (   SELECT [id]       ,[date]       ,[ordnum]       ,
[customer]  ,[amt]   ,[gm pc]   FROM [DbName].[dbo].[tblSales]  ) as [_]
where [date]>='2022-01-01T00:00:00.000'
Run Code Online (Sandbox Code Playgroud)

示例2:

select [_].[id],      [_].[date],   [_].[ordnum],  [_].[customer], [_].[amt], 
[_].[gm pc]  
from   (  SELECT [id] ,[date] ,[ordnum] ,  [customer]  ,[amt]  ,[gm pc]   
FROM [DbName].[dbo].[tblSales]  ) as [_]  where [_].[date] >= 
convert(datetime2, '2020-01-01 00:00:00') 
    and [_].[date] < convert(datetime2, '2021-01-01 00:00:00')
Run Code Online (Sandbox Code Playgroud)

因此在子查询中它选择所有行。然后在外部查询中应用 where 条件。

如果它确实像这样工作,则意味着子查询将执行全表扫描,然后将 where 子句应用于结果。或者此查询是否经过优化,以便将 where 子句直接应用于表?

Pau*_*ite 13

SQL 文本表达了所需的逻辑结果。SQL Server 基于成本的优化器找到了实现该逻辑要求的有效物理方法。当然,结果保证与 SQL 指定的相同(对于所有可能的数据值)。

优化器所做的基本事情之一是将过滤条件(谓词)尽可能地推向执行计划的下方(向叶方向)。

所以,是的,出于所有实际目的,像您这样的示例“保证”不会按字面意思执行完整扫描,然后再进行过滤。过滤条件通常将作为扫描的一部分进行评估,或者如果有合适的索引可用,则更好地作为索引范围搜索进行评估。

如果它确实像这样工作,则意味着子查询将执行全表扫描,然后将 where 子句应用于结果。

您似乎仍然在考虑执行计划,就好像每个运算符在将结果行传递给下一个运算符之前都执行完成。但事实并非如此。有关详细信息,请参阅我的文章迭代器、查询计划以及它们为何向后运行。