设计和实现计划指南

如果您无法或不希望直接更改查询文本,则可以使用计划指南来优化查询性能。计划指南通过将查询提示或固定的查询计划附加到查询来影响查询的优化。可以创建计划指南来匹配下列上下文中执行的查询:

  • OBJECT 计划指南与在 Transact-SQL 存储过程、用户定义标量函数、多语句用户定义表值函数和 DML 触发器上下文中执行的查询匹配。

  • SQL 计划指南与在独立 Transact-SQL 语句和不属于数据库对象的批处理上下文中执行的查询匹配。基于 SQL 的计划指南还可用于与参数化为指定形式的查询匹配。

  • TEMPLATE 计划指南与参数化为指定形式的独立查询匹配。这些计划指南用于覆盖查询类的数据库的当前 PARAMETERIZATION 数据库 SET 选项。

有关详细信息,请参阅了解计划指南

可创建的计划指南总数仅受可用系统资源的限制。尽管如此,计划指南还是应当限于针对提高或稳定性能的关键查询。计划指南不应用来影响已部署应用程序的大部分查询负荷。

建议在将应用程序升级到 SQL Server 的新版本时,重新评估和测试计划指南定义。性能优化要求和计划指南匹配行为可能会发生更改。尽管无效的计划指南不会导致查询失败,但仍应在不使用计划指南的情况下对计划进行编译。升级数据库后,建议使用 sys.fn_validate_plan_guide 函数执行下列任务来验证现有的计划指南。或者,可以使用 SQL Server Profiler 中的 Plan Guide Unsuccessful 事件来监视是否有无效的计划指南。

注意注意

只能在 SQL Server Standard Edition、Developer Edition、Evaluation Edition 和 Enterprise Edition 中使用计划指南;不过,在任何版本中都可看到计划指南。包含计划指南的数据库可以附加到任何版本。将数据库还原或附加到升级版本的 SQL Server 后,计划指南保持不变。

将查询提示附加到计划指南

计划指南中可以使用有效查询提示的任何组合。当计划指南与某一查询匹配时,计划指南提示子句中指定的 OPTION 子句将先添加到该查询中,然后该查询才会进行编译和优化。如果与计划指南匹配的查询已包含 OPTION 子句,则计划指南中指定的查询提示将替换查询中已存在的查询提示。但是,对于要与已包含 OPTION 子句的查询匹配的计划指南,在 sp_create_plan_guide 语句中指定要匹配的查询文本时,必须包含查询的 OPTION 子句。若要将计划指南中指定的提示添加到查询中已存在的提示,而不是替换已存在的提示,则必须在计划指南的 OPTION 子句中同时指定原始提示和附加提示。

注意事项注意

计划指南错用查询提示会导致出现编译、执行或性能问题。因此计划指南应仅由经验丰富的开发人员和数据库管理员使用。

计划指南中常用的查询提示

能够从计划指南中受益的查询通常是基于参数的,并且性能较差,因为它们使用的是参数值不表示最差情况或最具代表性方案的缓存查询计划。OPTIMIZE FOR 查询提示和 RECOMPILE 查询提示可用于解决这一问题。优化查询时,OPTIMIZE FOR 会指示 SQL Server 使用参数的特定值。执行后,RECOMPILE 指示服务器放弃查询计划,并在下次执行相同的查询时强制查询优化器重新编译新的查询计划。有关示例,请参阅了解计划指南

此外,您可以指定表提示 INDEX 和 FORCESEEK 作为查询提示。指定为查询提示时,这些提示的行为类似于内联表提示或视图提示。INDEX 提示强制查询优化器仅使用指定的索引来访问被引用表或视图中的数据。FORCESEEK 提示强制优化器仅使用索引查找操作来访问被引用表或视图中的数据。这些提示提供了附加的计划指南功能并允许用户更多地干预使用计划指南的查询的优化。有关示例,请参阅在计划指南中使用 INDEX 和 FORCESEEK 查询提示

将查询计划附加到计划指南

当您注意到对于特定查询现有的执行计划比优化器选择的计划执行得更好时,应用固定查询计划的计划指南将非常有用。请注意,将固定计划应用到查询时,查询优化器无法再根据统计信息和索引中的更改调整查询计划。考虑使用固定查询计划的计划指南时,一定要将应用固定计划的好处与无法随着数据分布和可用索引的更改自动修正计划的缺陷进行对比。

通过在 sp_create_plan_guide 语句的 xml_showplan 参数中指定计划的 XML 显示计划,或者在 sp_create_plan_guide_from_handle 语句中指定缓存计划的计划句柄,可以将特定的查询计划附加到计划指南。这两种方法都会将固定查询计划应用到目标查询。

符合要求的计划指南

计划指南的作用域是在其中创建这些计划指南的数据库。因此,执行查询时,只有处于当前状态的数据库中的计划指南可以与该查询匹配。例如,如果 AdventureWorks2008R2 是当前数据库并执行下面的查询:

SELECT FirstName, LastName FROM Person.Person;

则只有 AdventureWorks2008R2 数据库中的计划指南可以与此查询匹配。

但是,如果 AdventureWorks2008R2 是当前数据库并运行下列语句:

USE DB1;

GO

SELECT FirstName, LastName FROM Person.Person;

则只有 DB1 中的计划指南可以与该查询匹配,这是因为该查询是在 DB1 的上下文中执行的。

对于基于 SQL 或 TEMPLATE 的计划指南,SQL Server 通过对 @module_or_batch 参数和 @params 参数的值逐个字符地进行对比来将这两个值与查询匹配。这意味着必须提供与 SQL Server 在实际批处理中接收的文本完全相同的文本。

@type = 'SQL' 且 @module_or_batch 设置为 NULL 时,@module_or_batch 的值将设置为 @stmt 的值。这意味着 statement_text 值的提供格式必须与其提交到 SQL Server 时所采用的格式完全相同(字符对字符)。不会执行内部转换来帮助完成该匹配。

通常,应该使用 SQL Server Profiler 测试计划指南,以验证查询与计划指南是否匹配。通过从 SQL Server Management Studio 中运行批处理来测试基于 SQL 或 TEMPLATE 的计划指南,可能会产生意外结果。有关详细信息,请参阅使用 SQL Server Profiler 创建和测试计划指南

注意注意

包含要对其创建计划指南的语句的批处理不能包含 USE database 语句。

计划指南对计划缓存的影响

对模块创建计划指南将会从计划缓存中删除该模块的查询计划。对批处理创建类型为 OBJECT 或 SQL 的计划指南会删除具有相同哈希值的批处理的查询计划。创建类型为 TEMPLATE 的计划指南会从该数据库中的计划缓存中删除所有单语句批处理。

计划指南语句

创建计划指南

禁用、启用或删除计划指南

获取有关当前数据库中的计划指南的信息

验证计划指南