SQL Server 有一个用于存储执行计划和数据缓冲区的内存池。池内分配给执行计划或数据缓冲区的百分比随系统状态动态波动。内存池中用于存储执行计划的部分称为过程缓存。
SQL Server 执行计划包含下列主要组件:
- 查询计划
执行计划的主体是一个重入的只读数据结构,可由任意数量的用户使用。这称为查询计划。查询计划中不存储用户上下文。内存中查询计划副本永远不超过两个:一 个副本用于所有的串行执行,另一个用于所有的并行执行。并行副本覆盖所有的并行执行,与并行执行的并行度无关。
- 执行上下文
每个正在执行查询的用户都有一个包含其执行专用数据(如参数值)的数据结构。此数据结构称为执行上下文。执行上下文数据结构可以重新使用。如果用户执行查询而其中的一个结构未使用,将会用新用户的上下文重新初始化该结构。
在 SQL Server 中执行任何 SQL 语句时,关系引擎将首先查看过程缓存中是否有用于同一 SQL 语句的现有执行计划。SQL Server 将重新使用找到的任何现有计划,从而节省重新编译 SQL 语句的开销。如果没有现有执行计划,SQL Server 将为查询生成新的执行计划。
SQL Server 有一个高效的算法,可查找用于任何特定 SQL 语句的现有执行计划。在大多数系统中,这种扫描所使用的最小资源比通过重新使用现有计划而不是编译每个 SQL 语句所节省的资源要少。
该算法将新的 SQL 语句与缓存内现有的未用执行计划相匹配,并要求所有的对象引用完全合法。例如,在下列 SELECT 语句中,第一个语句与现有计划不匹配,而第二个语句匹配:
当存在单一高速缓存不足的情况时,用户线程将会从过程缓存中删除执行计划。它们强制实施最大单一缓存大小和最大单一缓存条目数的策略。
以下示例说明会从过程缓存中删除哪些执行计划:
- 一个经常被引用的执行计划,该计划的开销从未等于零。除非遇到内存不足和当前开销为零的情况,否则该计划保留在过程缓存中,不会被删除。
- 插入的一个即席执行计划,并且在内存不足情况出现之前没有再次引用该计划。由于即席计划在初始化后当前开销为零,因此在数据库引擎检查执行计划时,会发现 当前开销为零,于是从过程缓存中删除该计划。如果不存在内存不足的情况,当前开销为零的即席执行计划将保留在过程缓存中。
| EventSubClass 值 | 说明 |
|---|---|
| 1 |
架构已更改。 |
| 2 |
统计信息已更改。 |
| 3 |
编译已延迟。 |
| 4 |
SET 选项已更改。 |
| 5 |
临时表已更改。 |
| 6 |
远程行集已更改。 |
| 7 |
FOR BROWSE 权限已更改。 |
| 8 |
查询通知环境已更改。 |
| 9 |
分区视图已更改。 |
| 10 |
游标选项已更改。 |
| 11 |
已请求 OPTION (RECOMPILE)。 |
|
|
|---|
| 当 AUTO_UPDATE_STATISTICS 数据库选项被设置为 ON 时,如果查询以表或索引视图为目标,而自上次执行后,表或索引视图的统计信息已更新或基数已发生很大变化,查询将被重新编译。此行为适用于标准用户定义 表、临时表以及由 DML 触发器创建的 inserted 和 deleted 表。如果过多的重新编译影响到查询的性能,请考虑将此设置更改为 OFF。当 AUTO_UPDATE_STATISTICS 数据库选项设置为 OFF 时,不会因统计信息或基数的更改而发生任何重新编译,但是,由 DML INSTEAD OF 触发器创建的 inserted 和 deleted 表除外。因为这些表是在 tempdb 中创建的,因此,是否重新编译访问这些表的查询取决于 tempdb 中 AUTO_UPDATE_STATISTICS 的设置。请注意,在 SQL Server 2000 中,即使此设置为 OFF,查询仍然会基于 DML 触发器 inserted 和 deleted 表的基数变化进行重新编译。有关禁用 AUTO_UPDATE_STATISTICS 的详细信息,请参阅使用统计信息提高查询性能。 |