节选自: https://learn.microsoft.com/zh-cn/sql/relational-databases/query-processing-architecture-guide?view=sql-server-ver16
优化 SELECT 语句
SELECT
语句是非程序性的,它不说明数据库服务器应用于检索所请求数据的确切步骤。 这意味着数据库服务器必须分析语句,以决定提取所请求数据的最有效方法。 这被称为“优化 SELECT
语句”。 处理此过程的组件称为“查询优化器”。 查询优化器的输入包括查询、数据库方案(表和索引的定义)以及数据库统计信息。 查询优化器的输出称为“查询执行计划”,有时也称为“查询计划”或为“执行计划”。 本文稍后将更详细地介绍执行计划的内容。
在优化单个 SELECT
语句期间查询优化器的输入和输出如下图中所示:
SELECT
语句只定义以下内容:
- 结果集的格式。 它通常在选择列表中指定。 然而,其他子句(如
ORDER BY
和GROUP BY
)也会影响结果集的最终格式。 - 包含源数据的表。 此表在
FROM
子句中指定。 - 就
SELECT
语句而言,表之间的逻辑关系。 这在联接规范中定义,联接规范可出现在WHERE
子句后的ON
子句或FROM
子句中。 - 为了符合
SELECT
语句的要求,源表中的行所必须满足的条件。 这些条件在WHERE
和HAVING
子句中指定。
查询执行计划定义:
-
访问源表的顺序。
数据库服务器一般可以按许多不同的序列访问基表以生成结果集。 例如,如果SELECT
语句引用三个表,数据库服务器可以先访问TableA
,使用TableA
中的数据从TableB
中提取匹配的行,然后使用TableB
中的数据从TableC
中提取数据。 数据库服务器访问表的其他顺序包括:TableC
、TableB
、TableA
或TableB
、TableA
、TableC
或TableB
、TableC
、TableA
或TableC
、TableA
、TableB
-
用于从每个表提取数据的方法。
访问每个表中的数据一般也有不同的方法。 如果只需要有特定键值的几行,数据库服务器可以使用索引。 如果需要表中的所有行,数据库服务器则可以忽略索引并执行表扫描。 如果需要表中的所有行,而有一个索引的键列在ORDER BY
中,则执行索引扫描而非表扫描可能会省去对结果集的单独排序。 如果表很小,则对该表的几乎所有访问来说,表扫描可能都是最有效的方法。 -
用于计算的方法,以及如何对每个表中的数据进行筛选、聚合和排序的方法。
从表访问数据时,可以使用不同的方法对数据进行计算,例如,计算标量值,以及对查询文本中定义的数据进行聚合和排序(例如,使用GROUP BY
或ORDER BY
子句时),以及如何筛选数据(例如在使用WHERE
或HAVING
子句时)。
从潜在的多个可能的计划中选择一个执行计划的过程称为“优化”。 查询优化器是数据库引擎最重要的组件之一。 虽然查询优化器在分析查询和选择计划时要使用一些开销,但当查询优化器选择了有效的执行计划时,这一开销将节省数倍。 例如,两家建筑公司可能拿到一所住宅的相同设计图。 如果一家公司开始时先花几天时间规划如何建造这所住宅,而另一家公司不做任何规划就开始施工,则花了时间规划项目的那家公司很可能首先完工。
SQL Server 查询优化器是基于成本的优化器。 就所使用的计算资源量而言,每个可能的执行计划都具有相关成本。 查询优化器必须分析可能的计划并选择一个预计成本最低的计划。 有些复杂的 SELECT
语句有成千上万个可能的执行计划。 在这些情况下,查询优化器不会分析所有可能的组合, 而是使用复杂的算法查找一个执行计划:其成本合理地接近最低可能成本。
SQL Server 查询优化器不只选择资源成本最低的执行计划,还选择能将结果最快地返回给用户且资源成本合理的计划。 例如,与串行处理查询相比,并行处理查询使用的资源一般更多但完成查询的速度更快。 因此如果不对服务器的负荷产生负面影响,SQL Server 查询优化器将使用并行执行计划返回结果。
SQL Server 查询优化器在估算用于从表或索引中提取信息的不同方法所需的资源成本时,依赖于分布统计信息。 为列和索引保留分布统计信息,并保存有关基础数据的密度 1 的信息。 这些信息表明特定索引或列中的值的选择性。 例如,在一个代表汽车的表中,很多汽车出自同一制造商,但每辆车都有唯一的车牌号 (VIN)。 因为 VIN 的密度比制造商低,所以 VIN 索引比制造商索引更具选择性。 如果索引统计信息不是当前的,则查询优化器可能无法对表的当前状态做出最佳选择。 有关密度的详细信息,请参阅 统计信息。
1 密度定义数据中存在的唯一值的分布,或给定列的重复值平均数。 密度与值的选择性成反比,密度越小,值的选择性越大。
SQL Server 查询优化器很重要,因为它可以使数据库服务器针对数据库内的更改情况进行动态调整,而无需程序员或数据库管理员输入。 这样程序员可以集中精力描述最终的查询结果。 他们可以相信每次运行语句时,SQL Server 查询优化器总能针对数据库的状态生成有效的执行计划。
备注
SQL Server Management Studio 有三个选项来显示执行计划:
- 估计的执行计划,该计划是由查询优化器生成的已编译计划。
- 实际执行计划,该计划与编译的计划及其执行上下文相同。 这包括在执行完成之后可用的运行时信息,例如执行警告,或在较新版本的数据库引擎中,在执行过程中使用的已用时间和 CPU 时间。
- 实时查询统计信息,这与编译的计划及其执行上下文相同。 这包括执行过程中的运行时信息,每秒更新一次。 例如,运行时信息包括流经操作符的实际行数。