适用于:SQL Server
Azure SQL 数据库
Azure SQL 托管实例
Microsoft Fabric 中的 SQL 数据库
本文详细介绍了各种智能查询处理 (IQP) 功能、发行说明和更多详细信息。 智能查询处理 (IQP) 功能系列包含有广泛影响的功能,既能提升现有工作负荷的性能,还能最大限度地减少实现工作量。
可以通过为数据库启用适用的数据库兼容级别,使工作负载自动适用于智能查询处理。 可使用 Transact-SQL 进行此设置。 例如,要将数据库的兼容性级别设置为 SQL Server 2022 (16.x):
ALTER DATABASE [WideWorldImportersDW]
SET COMPATIBILITY_LEVEL = 160;
有关新版本引入的更改的详细信息,请参阅:
批处理模式自适应联接
适用于:SQL Server(从 SQL Server 2017 (14.x) 开始)和 Azure SQL 数据库
批处理模式自适应联接功能通过使用单个缓存计划,可将哈希联接或嵌套循环联接方法的选择延迟到在扫描完第一个输入之后。 自适应联接运算符可定义用于决定何时切换到嵌套循环计划的阈值。 因此,你的执行计划可以在执行期间动态切换到更优的联接策略。
有关详细信息,包括如何在不更改兼容性级别的情况下禁用自适应连接,请参阅了解自适应连接。
适用于 MSTVF 的交错执行
适用于:SQL Server(从 SQL Server 2017 (14.x) 开始)和 Azure SQL 数据库
多语句表值函数 (MSTVF) 是一种用户定义函数,可以接受参数、执行多个 T-SQL 语句和 RETURN 表。
交错执行有助于解决由于与 MSTVF 关联的固定基数估算而导致的工作负载性能问题。 通过交错执行,函数中的实际行计数可用于做出更明智的下游查询计划决策。
自 SQL Server 2014 (12.x) 起,MSTVF 的固定基数猜测为“100”,而早期 SQL Server 版本为“1”。
交错执行可更改单一查询执行的优化和执行阶段之间的单向边界,并使计划能够根据修订后的基数估值进行调整。 在优化期间,如果数据库引擎遇到使用 多语句表值函数(MSTVF)的交错执行候选项,优化将暂停,执行适用的子树,捕获准确的基数估计,然后恢复下游操作的优化。
下图显示了实时查询统计信息输出结果,它是整个执行计划的一个子集,展示了 MSTVFs 的固定基数估计值所带来的影响
可查看实际行流与估计行数。 该方案中有三个值得注意的部分(流程从右向左):
- MSTVF 表扫描的固定估计值为 100 行。 然而,对于此示例,有 527,597 行流经此 MSTVF 表扫描,如通过“527597 行,共 100 行”的实际与估值的实时查询统计信息中所示,因此固定估值偏差显著。
- 对于嵌套循环操作,仅假定联接外侧输入将返回 100 行。 鉴于 MSTVF 实际返回的行数较多,您可能会更好地完全采用另一种联接算法。
- 对于 Hash Match 操作,请注意那个小警告图标,它在这种情况下表示发生了磁盘溢出。
将之前的计划与通过启用交替执行生成的实际计划进行对比:
- MSTVF 表扫描现在反映了准确的基数估计。 另请注意该表扫描与其他操作的重排序。
- 而关于联接算法,我们已改为从嵌套循环操作切换到哈希匹配操作,后者在涉及大量行时更优。
- 另请注意,我们不再出现溢出警告,因为系统会根据 MSTVF 表扫描输出的实际行数分配更多内存。
可进行交错执行的语句
在交错执行中,引用 MSTVF 的语句当前必须为只读,且不能属于数据修改操作的一部分。 此外,如果 MSTVF 不使用运行时常量,则它们不符合交错执行的条件。
交错执行的优点
一般而言,估计行数与实际行数之间的偏差越大,再加上下游计划操作的数量越多,对性能的影响就越大。
一般来说,交错执行对以下情况中的查询有益:
中间结果集的估计行数与实际行数之间存在较大偏差(在本例中为 MSTVF)。
整个查询对中间结果集规模的变化十分敏感。 通常情况下,当查询计划中某个子树上方存在一棵复杂的树时,就会发生这种情况。
来自 MSTVF 的基本
SELECT *不会从交错执行中受益。
交错执行的开销
开销应极少甚至没有。 MSTVF 已在引入交错执行前具体化,但区别是现在已允许延迟优化,并可使用具体化行集的基数估算。 与任何会影响执行计划的更改一样,某些计划可能会发生这样的变化:虽然该子树的基数更准确了,但整个查询的执行计划反而变得更差。 缓解可包含还原兼容级别或使用查询存储来强制计划的非回归版本。
交错执行和顺序执行
交错执行计划一旦被缓存,基于首次执行时修订后的估计值的计划就会用于后续执行,而无需重新实例化交错执行。
跟踪交错执行活动
可在实际查询执行计划中查看使用情况属性:
| 执行计划属性 | Description |
|---|---|
| ContainsInterleavedExecutionCandidates | 适用于 QueryPlan 节点。 当 true 时,表示该计划包含交错执行候选方案。 |
| IsInterleavedExecuted | RelOp 下 TVF 节点的 RuntimeInformation 元素的属性。 当 true 时,表示该操作已作为交错执行的一部分被实体化。 |
还可以通过以下扩展事件跟踪交错执行的发生情况:
| XEvent | Description |
|---|---|
interleaved_exec_status |
发生交错执行时将引发此事件。 |
interleaved_exec_stats_update |
此事件描述了由交错执行更新的基数估计。 |
Interleaved_exec_disabled_reason |
当可能具有交错执行候选项的查询实际上未能交错执行时,将触发此事件。 |
必须先执行查询,才能使交错执行修正 MSTVF 的基数估计。 但是,如果存在交错执行候选项,估计执行计划仍会通过 ContainsInterleavedExecutionCandidates showplan 属性显示这一点。
交错式执行缓存
如果计划被清除或从缓存中逐出,当查询执行时,会进行使用交错执行的新编译。
使用 OPTION (RECOMPILE) 的语句使用交错执行创建新计划,而不是将其缓存。
交错执行和查询存储互操作性
使用交错执行的计划可强制使用。 该计划是基于初始执行结果修正了基数估计的版本。
在不更改兼容级别的情况下禁用交错执行
可在数据库或语句范围内禁用交错执行,同时将数据库兼容性级别维持在 140 或更高。 若要为所有源自该数据库的查询执行禁用交错执行,请在相应数据库的上下文中执行以下命令:
-- SQL Server 2017
ALTER DATABASE SCOPED CONFIGURATION SET DISABLE_INTERLEAVED_EXECUTION_TVF = ON;
-- Starting with SQL Server 2019, and in Azure SQL Database
ALTER DATABASE SCOPED CONFIGURATION SET INTERLEAVED_EXECUTION_TVF = OFF;
启用后,此设置在 sys.database_scoped_configurations 中将显示为已启用。 若要为所有源自该数据库的查询执行重新启用交错执行,请在相应数据库的上下文中执行以下语句:
-- SQL Server 2017
ALTER DATABASE SCOPED CONFIGURATION SET DISABLE_INTERLEAVED_EXECUTION_TVF = OFF;
-- Starting with SQL Server 2019, and in Azure SQL Database
ALTER DATABASE SCOPED CONFIGURATION SET INTERLEAVED_EXECUTION_TVF = ON;
此外,将 DISABLE_INTERLEAVED_EXECUTION_TVF 指定为 USE HINT 查询提示也可对特定查询禁用交错执行。 例如:
SELECT [fo].[Order Key],
[fo].[Quantity],
[fol].[OutlierEventQuantity]
FROM [Fact].[Order] AS [fo]
INNER JOIN [Fact].[WhatIfOutlierEventQuantity]('Mild Recession', '1-01-2013', '10-15-2014') AS [fol]
ON [fo].[Order Key] = [fol].[Order Key]
AND [fo].[City Key] = [fol].[City Key]
AND [fo].[Customer Key] = [fol].[Customer Key]
AND [fo].[Stock Item Key] = [fol].[Stock Item Key]
AND [fo].[Order Date Key] = [fol].[Order Date Key]
AND [fo].[Picked Date Key] = [fol].[Picked Date Key]
AND [fo].[Salesperson Key] = [fol].[Salesperson Key]
AND [fo].[Picker Key] = [fol].[Picker Key]
OPTION (USE HINT('DISABLE_INTERLEAVED_EXECUTION_TVF'));
USE HINT 查询提示优先于数据库范围配置或跟踪标志设置。
标量用户定义函数(UDF)内联
适用于:SQL Server(从 SQL Server 2019 (15.x) 开始)和 Azure SQL 数据库
标量 UDF 内联会自动将标量 UDF转换为关系表达式。 并将它们嵌入正在调用的 SQL 查询中。 此转换提升了利用标量 UDF 的工作负载的性能。 标量 UDF 内联有助于对 UDF 内部操作进行基于成本的优化。 结果是生成高效、面向集合且并行的执行计划,而非低效、迭代且串行的执行计划。 该功能在数据库兼容性级别为 150 或更高时默认启用。
有关更多信息,请参阅标量 UDF 内联。
表变量延迟编译
适用于:SQL Server(从 SQL Server 2019 (15.x) 开始)和 Azure SQL 数据库
表变量延迟编译功能提升了计划质量和引用表变量的查询的整体性能。 在优化和初始计划编译期间,此功能会传递基于实际表变量行数的基数估计。 然后,此确切的行计数信息用于优化下游计划操作。
采用表变量延迟编译后,引用表变量的语句的编译将推迟到该语句首次实际执行时。 此延迟编译行为与临时表的行为相同。 这一更改会使用实际基数,而不是原先的一行估计。
要启用表变量延迟编译,请为查询运行时连接到的数据库启用数据库兼容性级别 150 或更高级别。
表变量延迟编译不会更改表变量的任何其他特性。 例如,此功能不会向表变量添加列统计信息。
表变量延迟编译不会增加重新编译频率。 而是,它改变了首次编译发生的位置。 生成的缓存计划是基于初始延迟编译表变量行计数生成的。 后续查询会重用缓存的计划。 该计划会被重复使用,直到其被逐出或重新编译。
用于初始计划编译的表变量行计数代表了一个典型值,这个值可能不同于固定行数的假设。 如果存在差异,下游操作将受益。 如果表变量行计数在整个执行过程中差别很大,则可能无法通过此功能来提升性能。
在不更改兼容性级别的情况下禁用表变量延迟编译
可在数据库或语句范围内禁用表变量延迟编译,同时将数据库兼容性级别维持在 150 或更高。 若要对源自数据库的所有查询禁用表变量延迟编译,请在对应数据库的上下文中执行以下示例:
ALTER DATABASE SCOPED CONFIGURATION SET DEFERRED_COMPILATION_TV = OFF;
若要对源自数据库的所有查询重新启用表变量延迟编译,请在对应数据库的上下文中执行以下示例:
ALTER DATABASE SCOPED CONFIGURATION SET DEFERRED_COMPILATION_TV = ON;
此外,还可以通过将 DISABLE_DEFERRED_COMPILATION_TV 指定为 USE HINT 查询提示,针对特定查询禁用表变量的延迟编译。 例如:
DECLARE @LINEITEMS TABLE (
L_OrderKey INT NOT NULL,
L_Quantity INT NOT NULL);
INSERT @LINEITEMS
SELECT L_OrderKey,
L_Quantity
FROM dbo.lineitem
WHERE L_Quantity = 5;
SELECT O_OrderKey,
O_CustKey,
O_OrderStatus,
L_QUANTITY
FROM ORDERS, @LINEITEMS
WHERE O_ORDERKEY = L_ORDERKEY
AND O_OrderStatus = 'O'
OPTION (USE HINT('DISABLE_DEFERRED_COMPILATION_TV'));
参数敏感度计划优化
适用于: SQL Server 2022 (16.x) 及更高版本
Azure SQL 数据库
Azure SQL 托管实例
参数敏感度计划 (PSP) 优化是智能查询处理系列功能的一部分。 它解决了参数化查询的单个缓存计划对于所有可能的传入参数值都不是最佳方案的情况。 这是数据分布不均匀的情况。
- 有关 PSP 优化的详细信息,请参阅参数敏感计划优化。
- 有关参数化和参数敏感性的详细信息,请参阅参数敏感性和参数和执行计划的重复使用。
近似查询处理
近似查询处理是新的功能系列。 它可以跨响应速度比绝对精度更为关键的大型数据集进行聚合。 例如,对 100 亿行数据计算 COUNT(DISTINCT()),并在仪表板上显示。 在这种情况下,绝对精度并不重要,而响应速度则至关重要。
近似去重计数
适用于:SQL Server(从 SQL Server 2019 (15.x) 开始)和 Azure SQL 数据库
新的 APPROX_COUNT_DISTINCT 聚合函数返回组中非 NULL 唯一值的近似数量。
从 SQL Server 2019 (15.x) 开始,无论兼容性级别如何,此功能均可用。
有关详细信息,请参阅 APPROX_COUNT_DISTINCT。
近似百分位数
适用于:SQL Server(从 SQL Server 2022 (16.x) 开始)和 Azure SQL 数据库
这些聚合函数可计算具有基于排名的可接受误差范围的大型数据集的百分位数,以帮助使用近似百分位数聚合函数快速做出决策。
有关详细信息,请参阅 APPROX_PERCENTILE_DISC 和 APPROX_PERCENTILE_CONT
行存储中的批处理模式
适用于:SQL Server(从 SQL Server 2019 (15.x) 开始)和 Azure SQL 数据库
行存储上的批处理模式可实现分析工作负载的批处理模式执行,而无需列存储索引。 此功能支持批处理模式,并支持用于磁盘堆和 B 树索引的位图筛选器。 行存储上的批处理模式可实现对所有现有支持批处理模式的运算符的支持。
可从行存储上的批处理模式中受益最多的现有查询包括:
- 大型行存储表之间的哈希联接
- 具有
GROUP BY多个不同值的查询 - 聚合函数,例如
SUM、COUNT、MIN、MAXAVG - 包含
OVER、PARTITION BY和ORDER BY(包括聚合函数、ROW_NUMBER和RANK)的窗口函数查询
Note
文档在提到索引时一般使用 B 树这个术语。 在行存储索引中,数据库引擎实现了 B+ 树。 这不适用于列存储索引或内存优化表上的索引。 有关详细信息,请参阅 SQL Server 以及 Azure SQL 索引体系结构和设计指南。
批模式执行概述
SQL Server 2012 (11.x) 引入了一项可加速分析工作负载的新功能,即列存储索引。 在 SQL Server 的每个后续版本中,列存储索引的用例和性能都有所提高。 在表上创建列存储索引可以提高分析工作负载的性能。 不过,有两套相关但不同的技术:
- 使用列存储索引,分析查询仅访问所需列中的数据。 与传统 rowstore 索引中的压缩相比,列存储格式中的页压缩也更有效。
- 使用批处理模式处理,查询运算符可以更高效地处理数据。 它们一次处理一批行,而不是一次只处理一行。 许多其他可伸缩性改进都与批处理模式处理相关。 若要详细了解批处理模式,请参阅执行模式。
两组功能协同工作,以改进输入/输出 (I/O) 和 CPU 利用率:
- 使用列存储索引后,你的更多数据可装入内存。 这会减少 I/O 工作负荷。
- 批处理模式处理可更有效地使用 CPU。
这两种技术尽可能利用彼此。 例如,批处理模式聚合可以作为列存索引扫描的一部分进行计算。 此外,借助批处理模式联接和批处理模式聚合,经过游程编码压缩的列存储数据可以得到更高效的处理。
但是,必须了解这两个功能是独立的:
- 你可以获取使用列存储索引的行模式计划。
- 你可以获取仅使用行存储索引的批处理模式计划。
结合使用这两种功能时,通常效果最佳。 在 SQL Server 2019 (15.x) 之前,SQL Server 查询优化器仅对涉及至少一个有列存储索引的表的查询考虑使用批处理模式处理。
列存储索引可能不适用于某些应用程序。 应用程序可能会使用列存储索引不支持的其他一些功能。 例如,直接在原地进行的修改与列存储压缩不兼容。 因此,带有聚集列存储索引的表不支持触发器。 更重要的是,列存储索引会给 DELETE 和 UPDATE 语句增加额外开销。
对于一些事务与分析混合工作负荷,事务工作负荷的开销超过了使用列存储索引的获益。 此类方案可以通过仅使用批处理模式处理来提高 CPU 使用率,以从中获益。 这就是为什么无论涉及哪种索引类型,行存储上的批处理模式功能都会考虑所有查询的批处理模式。
可能受益于行存储批处理模式的工作负载
以下工作负载可能会受益于行存储上的批处理模式:
- 工作负载的很大一部分由分析查询组成。 通常情况下,这些查询使用联接或聚合等运算符,可处理数十万行或更多行。
- 工作负载受 CPU 限制。 如果瓶颈为 I/O(输入/输出),仍建议在可能的情况下尽可能考虑列存储索引。
- 创建列存储索引会给工作负载中的事务处理部分带来过多开销。 或者,创建列存储索引不可行,因为应用程序依赖于列存储索引尚不支持的功能。
Note
行存储上的批处理模式仅通过降低 CPU 消耗来发挥作用。 如果瓶颈与 I/O 相关,并且数据尚未缓存(“冷”缓存),则行存储上的批处理模式不会改善查询运行时间。 同样,如果计算机上没有足够的内存来缓存所有数据,则性能改进不太可能。
启用行存储上的批处理模式后,会发生哪些变化?
行存储上的批处理模式要求数据库的兼容性级别为 150。
即使查询无法访问具有列存储索引的任何表,查询处理器也使用启发式来决定是否考虑批处理模式。 启发式规则包括以下检查项:
- 对输入查询中的表大小、所用运算符和估计基数进行初步检查。
- 其他检查点,因为优化器会发现新的、成本更低的查询计划。 如果这些替代计划没有大量使用批处理模式,优化器会停止探索批处理模式替代方案。
如果使用行存储上的批处理模式,则会发现在查询计划中实际运行模式为批处理模式。 扫描运算符对磁盘堆和 B 树索引使用批处理模式。 此批处理模式扫描可以评估批处理模式位图筛选器。 你可能还会在执行计划中看到其他批处理模式操作符。 例如,哈希联接、基于哈希的聚合、排序、窗口聚合、筛选器、串联和计算标量运算符。
Remarks
查询计划并不总是使用批处理模式。 查询优化器可能会认为批处理模式对查询没有益处。
查询优化器搜索空间正在发生变化。 因此,如果你得到的是行模式执行计划,它可能与在较低兼容级别下得到的执行计划并不相同。 另外,如果你得到的是批处理模式执行计划,它可能与你在使用列存储索引时得到的执行计划不同。
对于混合使用列存储索引和行存储索引的查询,由于新的行存储批处理模式扫描,查询计划也可能会发生变化。
用于行存储扫描的新批处理模式当前存在以下限制:
- 它不会对内存中 OLTP 表生效,也不会对磁盘上的堆和 B 树之外的任何索引生效。
- 如果读取或筛选的是大型对象 (LOB) 列,它也不会生效。 此限制包括稀疏列集和 XML 列。
有些查询即使使用列存储索引,也无法使用批处理模式。 例如,涉及游标的查询。 这些相同的排除情况同样适用于行存储上的批处理模式。
对行存储配置批处理模式
BATCH_MODE_ON_ROWSTORE
数据库范围的配置默认为 ON。
无需更改数据库兼容性级别,即可禁用行存储上的批处理模式:
-- Disabling batch mode on rowstore
ALTER DATABASE SCOPED CONFIGURATION SET BATCH_MODE_ON_ROWSTORE = OFF;
-- Enabling batch mode on rowstore
ALTER DATABASE SCOPED CONFIGURATION SET BATCH_MODE_ON_ROWSTORE = ON;
可以通过数据库范围的配置来禁用行存储上的批处理模式。 但仍可使用 ALLOW_BATCH_MODE 查询提示,在查询一级替代设置。 以下示例启用行存储的批处理模式,即使通过数据库作用域配置禁用了该功能:
SELECT [Tax Rate],
[Lineage Key],
[Salesperson Key],
SUM(Quantity) AS SUM_QTY,
SUM([Unit Price]) AS SUM_BASE_PRICE,
COUNT(*) AS COUNT_ORDER
FROM Fact.OrderHistoryExtended
WHERE [Order Date Key] <= DATEADD(dd, -73, '2015-11-13')
GROUP BY [Tax Rate], [Lineage Key], [Salesperson Key]
ORDER BY [Tax Rate], [Lineage Key], [Salesperson Key]
OPTION (RECOMPILE, USE HINT('ALLOW_BATCH_MODE'));
还可以使用 DISALLOW_BATCH_MODE 查询提示,对特定查询禁用行存储上的批处理模式。 请参阅以下示例:
SELECT [Tax Rate],
[Lineage Key],
[Salesperson Key],
SUM(Quantity) AS SUM_QTY,
SUM([Unit Price]) AS SUM_BASE_PRICE,
COUNT(*) AS COUNT_ORDER
FROM Fact.OrderHistoryExtended
WHERE [Order Date Key] <= DATEADD(dd, -73, '2015-11-13')
GROUP BY [Tax Rate], [Lineage Key], [Salesperson Key]
ORDER BY [Tax Rate], [Lineage Key], [Salesperson Key]
OPTION (RECOMPILE, USE HINT('DISALLOW_BATCH_MODE'));
查询处理反馈功能
查询处理反馈功能是智能查询处理系列功能的一部分。
查询处理反馈是 SQL Server、Azure SQL 数据库和 Azure SQL 托管实例中的查询处理器使用有关查询执行的历史数据来决定查询是否可以从编译和执行方式的一个或多个更改中获得帮助的过程。 性能数据在查询存储中收集,并提出了各种改进查询执行的建议。 如果成功,我们会将这些修改持久保存到磁盘、内存和/或 查询存储 中,以供后续使用。 如果建议没有带来足够的改进,它们就会被丢弃,查询将在没有反馈的情况下继续执行。
有关 SQL Server 的不同版本或 Azure SQL 数据库或 Azure SQL 托管实例中提供哪些查询处理反馈功能的信息,请参阅 SQL 数据库中的智能查询处理,或有关每个反馈功能的以下文章。
内存授予反馈
内存授予反馈已在 SQL Server 过去几个主要版本中陆续引入。
批处理模式内存授予反馈
有关批处理模式内存授予反馈的信息,请访问批处理模式内存授予反馈。
行模式内存授予反馈
有关行模式内存授予反馈的信息,请访问行模式内存授予反馈。
百分位和持久模式内存授予反馈
有关百分位数和持久性模式内存授予反馈的信息,请访问百分位数和持久性模式内存授予反馈。
并行处理度 (DOP) 反馈
有关 DOP 反馈的信息,请访问并行度 (DOP) 反馈。
基数估计(CE)反馈
有关 CE 反馈的信息,请参阅基数估计 (CE) 反馈。
通过查询存储强制使用优化计划
有关使用查询存储优化计划强制的信息,请访问 使用查询存储优化计划强制。