查询提示 (Transact-SQL)

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例

查询提示指定在查询范围内使用所指示的提示。 它们影响语句中的所有运算符。 如果 UNION 主查询涉及,则只有涉及操作的最后一个 UNION 查询才能有子 OPTION 句。 查询提示作为 OPTION 子句的一部分指定。 如果一个或多个查询提示导致查询优化器生成无效计划,便会导致错误 8622 生成。

注意

由于 SQL Server 查询优化器通常会为查询选择最佳执行计划,我们建议资深开发人员和数据库管理员仅在不得已时使用提示。

适用于:

Transact-SQL 语法约定

语法

<query_hint> ::=
{ { HASH | ORDER } GROUP
  | { CONCAT | HASH | MERGE } UNION
  | { LOOP | MERGE | HASH } JOIN
  | DISABLE_OPTIMIZED_PLAN_FORCING
  | EXPAND VIEWS
  | FAST <integer_value>
  | FORCE ORDER
  | { FORCE | DISABLE } EXTERNALPUSHDOWN
  | { FORCE | DISABLE } SCALEOUTEXECUTION
  | IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX
  | KEEP PLAN
  | KEEPFIXED PLAN
  | MAX_GRANT_PERCENT = <numeric_value>
  | MIN_GRANT_PERCENT = <numeric_value>
  | MAXDOP <integer_value>
  | MAXRECURSION <integer_value>
  | NO_PERFORMANCE_SPOOL
  | OPTIMIZE FOR ( @variable_name { UNKNOWN | = <literal_constant> } [ , ...n ] )
  | OPTIMIZE FOR UNKNOWN
  | PARAMETERIZATION { SIMPLE | FORCED }
  | QUERYTRACEON <integer_value>
  | RECOMPILE
  | ROBUST PLAN
  | USE HINT ( <use_hint_name> [ , ...n ] )
  | USE PLAN N'<xml_plan>'
  | TABLE HINT ( <exposed_object_name> [ , <table_hint> [ [ , ] ...n ] ] )
  | FOR TIMESTAMP AS OF '<point_in_time>'
}

<table_hint> ::=
{ NOEXPAND [ , INDEX ( <index_value> [ , ...n ] ) | INDEX = ( <index_value> ) ]
  | INDEX ( <index_value> [ , ...n ] ) | INDEX = ( <index_value> )
  | FORCESEEK [ ( <index_value> ( <index_column_name> [ , ... ] ) ) ]
  | FORCESCAN
  | HOLDLOCK
  | NOLOCK
  | NOWAIT
  | PAGLOCK
  | READCOMMITTED
  | READCOMMITTEDLOCK
  | READPAST
  | READUNCOMMITTED
  | REPEATABLEREAD
  | ROWLOCK
  | SERIALIZABLE
  | SNAPSHOT
  | SPATIAL_WINDOW_MAX_CELLS = <integer_value>
  | TABLOCK
  | TABLOCKX
  | UPDLOCK
  | XLOCK
}

<use_hint_name> ::=
{ 'ASSUME_JOIN_PREDICATE_DEPENDS_ON_FILTERS'
  | 'ASSUME_MIN_SELECTIVITY_FOR_FILTER_ESTIMATES'
  | 'ASSUME_FULL_INDEPENDENCE_FOR_FILTER_ESTIMATES'
  | 'ASSUME_PARTIAL_CORRELATION_FOR_FILTER_ESTIMATES'
  | 'DISABLE_BATCH_MODE_ADAPTIVE_JOINS'
  | 'DISABLE_BATCH_MODE_MEMORY_GRANT_FEEDBACK'
  | 'DISABLE_DEFERRED_COMPILATION_TV'
  | 'DISABLE_INTERLEAVED_EXECUTION_TVF'
  | 'DISABLE_OPTIMIZED_NESTED_LOOP'
  | 'DISABLE_OPTIMIZER_ROWGOAL'
  | 'DISABLE_PARAMETER_SNIFFING'
  | 'DISABLE_ROW_MODE_MEMORY_GRANT_FEEDBACK'
  | 'DISABLE_TSQL_SCALAR_UDF_INLINING'
  | 'DISALLOW_BATCH_MODE'
  | 'ENABLE_HIST_AMENDMENT_FOR_ASC_KEYS'
  | 'ENABLE_QUERY_OPTIMIZER_HOTFIXES'
  | 'FORCE_DEFAULT_CARDINALITY_ESTIMATION'
  | 'FORCE_LEGACY_CARDINALITY_ESTIMATION'
  | 'QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_n'
  | 'QUERY_PLAN_PROFILE'
}

注意

若要查看 SQL Server 2014 (12.x) 及更早版本的 Transact-SQL 语法,请参阅早期版本文档

参数

{ HASH | ORDER } GROUP

指定查询或DISTINCT子句描述的GROUP BY聚合应使用哈希或排序。

{ MERGE | HASH | CONCAT } UNION

指定所有 UNION 操作都通过合并、哈希或串联 UNION 集运行。 如果指定了多个 UNION 提示,查询优化器将从指定的提示中选择成本最低的策略。

{ LOOP | MERGE | HASH } JOIN

指定所有联接操作由LOOP JOIN整个MERGE JOINHASH JOIN查询或整个查询执行。 如果你指定了多个联接提示,优化器从可使用的联接策略中选择支出最低的。

如果在特定表对的同一查询子 FROM 句中指定联接提示,则此联接提示优先于两个表的联接。 不过,仍必须遵循查询提示。 面向表对的联接提示可能只限制在查询提示中选择可用的联接方法。 有关详细信息,请参阅 联接提示

DISABLE_OPTIMIZED_PLAN_FORCING

适用于:SQL Server(SQL Server 2022 (16.x) 及更高版本)

对查询禁用优化计划强制执行

优化计划强制执行减少了重复强制查询的编译开销。 生成查询执行计划后,将会存储特定编译步骤以作为优化重播脚本重复使用。 在查询存储中,优化重播脚本作为压缩的显示计划 XML 的一部分存储在隐藏属性 OptimizationReplay 中。

EXPAND VIEWS

指定展开索引视图。 此外,还指定查询优化器不将任何索引视图视为任何查询部分的替代。 当查询文本中的视图名称被视图定义替换时,视图展开。

实际上,该查询提示不允许在查询计划中直接使用索引视图和直接在索引视图上使用索引。

注意

如果查询部分有对视图的 SELECT 直接引用,则索引视图将保持精简。 如果指定 WITH (NOEXPAND)WITH (NOEXPAND, INDEX( <index_value> [ , *...n* ] ) ),视图也会保持精简状态。 有关查询提示 NOEXPAND的详细信息,请参阅 使用 NOEXPAND

该提示仅影响语句SELECT部分中的视图,包括这些视图,MERGEINSERTUPDATE以及DELETE语句。

FAST integer_value

指定对查询进行优化,以便快速检索前 integer_value 行。 此结果是非负整数。 在返回前 integer_value 行后,查询继续执行并生成完整的结果集。

FORCE ORDER

指定在查询优化过程中保持由查询语法指示的联接顺序。 使用 FORCE ORDER 不会影响查询优化器可能的角色逆转行为。

注意

MERGE在语句中,除非指定了子句,WHEN SOURCE NOT MATCHED否则在目标表作为默认联接顺序之前访问源表。 指定 FORCE ORDER 保留此默认行为。

{ FORCE | DISABLE } EXTERNALPUSHDOWN

强制或禁用向下推送 Hadoop 中符合条件的表达式的计算。 仅适用于使用 PolyBase 的查询。 不会向下推送到 Azure 存储。

{ FORCE | DISABLE } SCALEOUTEXECUTION

强制或禁用 PolyBase 查询的横向扩展执行,这些查询使用 SQL Server 2019 大数据群集中的外部表。 仅使用 SQL 大数据群集的主实例的查询遵循此提示。 横向扩展发生在大数据群集的计算池中。

KEEP PLAN

更改临时表的 重新编译阈值 ,使其与永久表的阈值相同。 如果对表进行了估计的索引列更改,则估计的重新编译阈值会启动查询的自动重新编译,方法是运行以下语句之一:

  • UPDATE
  • DELETE
  • MERGE
  • INSERT

指定 KEEP PLAN 可确保查询在对表进行多次更新时不经常重新编译。

KEEPFIXED PLAN

强制查询优化器不因统计信息变化而重新编译查询。 指定 KEEPFIXED PLAN 可确保仅当基础表的架构发生更改或 sp_recompile 针对这些表运行时,查询才会重新编译。

IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX

适用范围:SQL Server(从 SQL Server 2012 (11.x) 开始) 。

防止查询使用非聚集内存优化列存储索引。 如果查询包含避免使用列存储索引的查询提示,而又包含支持使用列存储索引的索引提示,那么这两个提示相互冲突,导致查询返回错误。

MAX_GRANT_PERCENT = <numeric_value>

适用于:SQL Server(从 SQL Server 2012 (11.x) Service Pack 3、SQL Server 2014 (12.x) Service Pack 2 开始)和 Azure SQL 数据库。

配置内存限制的最大 PERCENT 内存授予大小。 如果查询在用户定义的资源池中运行,则保证查询不超过此限制。 在此情况下,如果查询没有所需的最小内存,系统将引发错误。 如果查询在系统池中运行(默认),则它至少会获得运行所需的内存。 如果 Resource Governor 设置低于此提示指定的值,则实际限制可能更低。 有效值介于 0.0 和 100.0 之间。

内存授予提示不适用于索引创建或索引重新生成。

MIN_GRANT_PERCENT = <numeric_value>

适用于:SQL Server(从 SQL Server 2012 (11.x) Service Pack 3、SQL Server 2014 (12.x) Service Pack 2 开始)和 Azure SQL 数据库。

配置的内存限制中的 PERCENT 最小内存授予大小。 查询保证会获取 MAX(required memory, min grant),因为至少需要必需内存才能启动查询。 有效值介于 0.0 和 100.0 之间。

无论大小如何,min_grant_percent 内存授予选项都会覆盖 sp_configure 选项(每次查询占用的最小内存 (KB))。 内存授予提示不适用于索引创建或索引重新生成。

MAXDOP <integer_value>

适用于:SQL Server(从 SQL Server 2008 (10.0.x) 开始)和 Azure SQL 数据库。

替代 sp_configure 的“最大并行度”配置选项。 还会替代指定此选项的查询 Resource Governor。 查询 MAXDOP 提示可以超出配置 sp_configure的值。 如果MAXDOP超出使用资源调控器配置的值,则数据库引擎使用 ALTER WORKLOAD GROUP 中所述的资源调控器MAXDOP值。 使用MAXDOP查询提示时,与最大并行度配置选项一起使用的所有语义规则都适用。 有关详细信息,请参阅 配置 max degree of parallelism 服务器配置选项

警告

如果 MAXDOP 设置为零,则服务器选择最大并行度。

MAXRECURSION <integer_value>

指定该查询允许的最大递归数。 number 是介于 0 和 32,767 之间的正整数。 如果指定 0,则没有限制。 如果未指定此选项,服务器的默认限制为 100。

在查询执行期间达到指定的或默认限制数 MAXRECURSION 时,查询结束并返回错误。

由于此错误,该语句的所有结果都被回滚。 如果语句是 SELECT 语句,则可能会返回部分结果或未返回任何结果。 所返回的任何部分结果都可能无法包括超过指定最大递归级别的递归级别上的所有行。

有关详细信息,请参阅 WITH common_table_expression

NO_PERFORMANCE_SPOOL

适用于:SQL Server(从 SQL Server 2016 (13.x) 开始)和 Azure SQL 数据库。

防止将 spool 运算符添加到查询计划(需要 spool 保证更新语义有效的计划除外)。 在某些情况下,spool 运算符可能会降低性能。 例如,如果有大量查询与 spool 操作并发运行,spool 将使用 tempdb 并会出现 tempdb 争用。

OPTIMIZE FOR ( @variable_name { UNKNOWN | = <literal_constant> } [ , ...n ] )

在编译和优化查询时指示查询优化器对局部变量使用特定值。 仅在查询优化期间使用该值,在查询执行期间不使用该值。

  • @variable_name

    查询中使用的局部变量的名称,可以将值分配给该变量以用于 OPTIMIZE FOR 查询提示。

  • UNKNOWN

    指定查询优化器在查询优化期间使用统计数据而不是初始值来确定局部变量的值。

  • literal_constant

    要分配@variable_nameOPTIMIZE FOR用于查询提示的文本常量值。 literal_constant 只在查询优化期间使用,在查询执行期间不用作 @variable_name 的值。 literal_constant 可以是任意可表达为文本常量的 SQL Server 系统数据类型。 literal_constant 的数据类型必须可隐式转换为@variable_name 在查询中引用的数据类型。

OPTIMIZE FOR 可能会对优化器的默认参数检测行为起反作用。 也可以在创建计划指南时使用 OPTIMIZE FOR 。 有关详细信息,请参阅重新编译存储过程

OPTIMIZE FOR UNKNOWN

指示查询优化器在所有列值中使用谓词的平均选择性,而不是在编译和优化查询时使用运行时参数值。

如果使用同一查询提示中的 OPTIMIZE FOR @variable_name = <literal_constant>OPTIMIZE FOR UNKNOWN,则查询优化器将使用为某个特定值指定的 literal_constant。 查询优化器会对其余变量值使用 UNKNOWN。 这些值仅用于查询优化期间,而不会用于查询执行期间。

PARAMETERIZATION { SIMPLE | FORCED }

指定 SQL Server 查询优化器在编译时应用于查询的参数化规则。

重要

PARAMETERIZATION查询提示只能在计划指南中指定,以替代数据库SET选项的PARAMETERIZATION当前设置。 无法直接在查询中指定它。

有关详细信息,请参阅使用计划指南指定查询参数化行为

SIMPLE 指示查询优化器尝试简单的参数化。 FORCED 指示查询优化器尝试强制参数化。 有关详细信息,请参阅查询处理体系结构指南中的强制参数化查询处理体系结构指南中的简单参数化

QUERYTRACEON <integer_value>

使用此选项可以仅在单查询编译期间启用影响计划的跟踪标志。 与其他查询级别选项类似,你可以将选项与计划指南一起使用,以匹配从任何会话中执行的查询文本,并在编译此查询时自动应用影响计划的跟踪标志。 仅查询优化器跟踪标志支持此选项 QUERYTRACEON 。 有关更多信息,请参见跟踪标记

如果使用不受支持的跟踪标志号,则使用此选项不会返回任何错误或警告。 如果指定的跟踪标志不是影响查询执行计划的跟踪标志,则将以无提示方式忽略该选项。

若要在查询中使用多个跟踪标志,请为每个不同的跟踪标志编号指定一个 QUERYTRACEON 提示。

RECOMPILE

指示 SQL Server 数据库引擎 为查询生成新的临时计划,并在查询完成执行后立即放弃该计划。 当同一查询在没有提示的情况下运行 RECOMPILE 时,生成的查询计划不会替换存储在缓存中的计划。 如果不指定RECOMPILE,数据库引擎将缓存查询计划并重复使用它们。 编译查询计划时, RECOMPILE 查询提示使用查询中任何局部变量的当前值。 如果查询在存储过程内,当前值会传递给任意参数。

RECOMPILE 是创建存储过程的有用替代方法。 RECOMPILEWITH RECOMPILE仅当存储过程内的查询子集(而不是整个存储过程)必须重新编译时,使用子句。 有关详细信息,请参阅重新编译存储过程RECOMPILE 创建计划指南时也很有用。

ROBUST PLAN

强制查询优化器尝试一个计划,该计划可能以性能为代价获得可能的最大行大小。 处理查询时,中间表和运算符可能需要存储和处理比任一输入行宽的行。 有时,行可能很宽,导致特定运算符无法处理行。 如果行这么宽,数据库引擎会在查询执行期间生成错误。 通过使用 ROBUST PLAN,指示查询优化器不要考虑可能遇到此问题的任何查询计划。

如果此类计划不可行,则查询优化器会返回错误,而不是将错误检测延迟到查询执行阶段。 行可以包含可变长度列;数据库引擎允许将行大小定义为超过数据库引擎处理能力的最大可能的大小。 通常,应用程序存储实际大小在数据库引擎处理能力范围内的行,而不管最大可能大小。 如果数据库引擎遇到过长的行,便会返回执行错误。

USE HINT ( 'hint_name' )

适用于:SQL Server(从 SQL Server 2016 (13.x) SP1 开始)和 Azure SQL 数据库。

向查询处理器提供一个或多个额外提示。 使用单引号内的提示名称指定额外的提示。

提示

提示名称不区分大小写。

支持以下提示名称:

提示 说明
'ASSUME_JOIN_PREDICATE_DEPENDS_ON_FILTERS' 在 SQL Server 2014(12.x)及更高版本的查询优化器 基数估算 模型下,SQL Server 使用简单包含假设而不是联接的默认基本包含假设生成查询计划。 此提示名称等效于 跟踪标志 9476。
'ASSUME_MIN_SELECTIVITY_FOR_FILTER_ESTIMATES' 会导致 SQL Server 在为了进行完全关联而对筛选的 AND 谓词进行估值时使用最小选择性来生成计划。 当与 SQL Server 2012 (11.x) 和早期版本的基数估计模型一起使用时,此提示名称等效于跟踪标志 4137,当跟踪标志 9471 与 SQL Server 2014(12.x)及更高版本的基数估计模型一起使用时,其效果类似。
'ASSUME_FULL_INDEPENDENCE_FOR_FILTER_ESTIMATES' 会导致 SQL Server 在为了实现完全独立而对筛选的 AND 谓词进行估值时使用最大选择性来生成计划。 此提示名称是 SQL Server 2012 (11.x) 和早期版本的基数估计模型的默认行为,等效于 在 SQL Server 2014 (12.x) 及更高版本中用于基数估计模型时跟踪标志 9472。

适用于: Azure SQL 数据库
'ASSUME_PARTIAL_CORRELATION_FOR_FILTER_ESTIMATES' 会导致 SQL Server 在为了进行部分关联而对筛选的 AND 谓词进行估值时使用最多到最少的选择性来生成计划。 此提示名称是 SQL Server 2014 (12.x) 及更高版本基数估计模型的默认行为。

适用于: Azure SQL 数据库
'DISABLE_BATCH_MODE_ADAPTIVE_JOINS' 禁用批处理模式自适应联接。 有关详细信息,请参阅批处理模式自适应联接

适用于:SQL Server 2017 (14.x) 及更高版本和 Azure SQL 数据库
'DISABLE_BATCH_MODE_MEMORY_GRANT_FEEDBACK' 禁用批处理模式内存授予反馈。 有关详细信息,请参阅批处理模式内存授予反馈

适用于:SQL Server 2017 (14.x) 及更高版本和 Azure SQL 数据库
'DISABLE_DEFERRED_COMPILATION_TV' 禁用表变量延迟编译。 有关详细信息,请参阅表变量延迟编译

适用于:SQL Server 2019 (15.x) 及更高版本和 Azure SQL 数据库
'DISABLE_INTERLEAVED_EXECUTION_TVF' 对多语句表值函数禁用交错执行。 有关详细信息,请参阅多语句表值函数的交错执行

适用于:SQL Server 2017 (14.x) 及更高版本和 Azure SQL 数据库
'DISABLE_OPTIMIZED_NESTED_LOOP' 指示查询处理器在生成查询计划时不对优化的嵌套循环联接使用排序操作(批处理排序)。 此提示名称等效于 一起跟踪标志 2340 和 8751。
'DISABLE_OPTIMIZER_ROWGOAL' 让 SQL Server 生成计划,它不对包含以下关键字的查询使用行目标修改:

- TOP
- OPTION (FAST N)
- IN
- EXISTS

此提示名称等效于 跟踪标志 4138。
'DISABLE_PARAMETER_SNIFFING' 指示查询优化器在使用一个或多个参数编译查询时,使用平均数据分布。 此指令让查询计划独立于编译查询时首次使用的参数值。 此提示名称等效于 跟踪标志 4136 或 数据库范围的配置 设置 PARAMETER_SNIFFING = OFF
'DISABLE_ROW_MODE_MEMORY_GRANT_FEEDBACK' 禁用行模式内存授予反馈。 有关详细信息,请参阅模式内存授予反馈

适用于:SQL Server 2019 (15.x) 及更高版本和 Azure SQL 数据库
'DISABLE_TSQL_SCALAR_UDF_INLINING' 禁用标量 UDF 内联。 有关详细信息,请参阅标量 UDF 内联

适用于:SQL Server 2019 (15.x) 及更高版本和 Azure SQL 数据库
'DISALLOW_BATCH_MODE' 禁用批处理模式执行。 有关详细信息,请参阅执行模式

适用于:SQL Server 2019 (15.x) 及更高版本和 Azure SQL 数据库
'ENABLE_HIST_AMENDMENT_FOR_ASC_KEYS' 针对需要对其执行基数估计的任何前导索引列,启用自动生成的快速统计信息(直方图修正)。 用于估计基数的直方图在查询编译时进行调整,以考虑此列的实际最大值或最小值。 此提示名称等效于 跟踪标志 4139。
'ENABLE_QUERY_OPTIMIZER_HOTFIXES' 启用查询优化器修补程序(SQL Server 累积更新和服务包中发布的更改)。 此提示名称等效于 跟踪标志 4199 或 数据库范围的配置 设置 QUERY_OPTIMIZER_HOTFIXES = ON
'FORCE_DEFAULT_CARDINALITY_ESTIMATION' 强制查询优化器使用与当前数据库兼容级别相对应的基数估计模型。 使用此提示替代 数据库范围的配置 设置 LEGACY_CARDINALITY_ESTIMATION = ON跟踪标志 9481。
'FORCE_LEGACY_CARDINALITY_ESTIMATION' 强制查询优化器使用 SQL Server 2012 (11.x) 及更早版本的基数估计模型。 此提示名称等效于 跟踪标志 9481 或 数据库范围的配置 设置 LEGACY_CARDINALITY_ESTIMATION = ON
'QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_n'1 强制查询优化器行为在查询级别发生。 此行为就像使用数据库兼容性级别 n 编译查询(其中,n 是受支持的数据库兼容性级别)。 有关 n 当前支持的值的列表,请参阅sys.dm_exec_valid_use_hints

适用于:SQL Server 2017 (14.x) CU 10 及更高版本,以及Azure SQL 数据库
'QUERY_PLAN_PROFILE'2 启用用于查询的轻型分析。 当包含此新提示的查询完成时,将触发新的扩展事件 query_plan_profile。 此扩展事件公开执行统计信息和实际执行计划 XML,类似于 query_post_execution_showplan 扩展事件,但仅适用于包含新提示的查询。

适用于:SQL Server 2016 (13.x) SP 2 CU 3、SQL Server 2017 (14.x) CU 11 及更高版本

1 如果通过数据库范围的配置、跟踪标志或其他查询提示(例如QUERYTRACEON)强制设置,提示QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_n不会替代默认或旧基数估计设置。 此提示仅影响查询优化器的行为。 它不影响可能依赖数据库兼容性级别的其他 SQL Server 功能(如某些数据库功能的可用性)。 有关详细信息,请参阅 开发人员的选择:提示查询执行模型

2 如果启用收集 query_post_execution_showplan 扩展事件,则会将标准分析基础结构添加到服务器上运行的每个查询,因此可能会影响服务器的整体性能。 如果启用扩展事件的集合 query_thread_profile 以改用轻型分析基础结构,这会导致性能开销要小得多,但仍会影响服务器的整体性能。 如果启用 query_plan_profile 扩展事件,则只会为随该 query_plan_profile 事件一起执行的查询启用轻型分析基础结构,因此不会影响服务器上的其他工作负荷。 使用此提示来分析特定查询,而不会影响服务器工作负载的其他部分。 有关轻型分析的详细信息,请参阅 查询分析基础结构

可以使用动态管理视图sys.dm_exec_valid_use_hints查询所有支持USE HINT的名称的列表。

重要

某些 USE HINT 提示可能与在全局级别或会话级别启用的跟踪标志或数据库范围的配置设置冲突。 在这种情况下,查询级别提示 (USE HINT) 始终优先。 USE HINT如果与另一个查询提示冲突,或查询级别(如 byQUERYTRACEON)启用的跟踪标志,则尝试执行查询时,SQL Server 将生成错误。

USE PLAN N'xml_plan'

强制查询优化器对由xml_plan指定的查询使用现有查询计划。 USE PLAN不能使用INSERTUPDATEMERGEDELETE语句指定。

此功能强制生成的执行计划与强制计划相同或类似。 由于生成的计划可能与指定的 USE PLAN计划不同,因此计划的性能可能会有所不同。 在极少数情况下,性能差异可能很大,也可能是负面的;在这种情况下,管理员必须删除强制计划。

TABLE HINT ( exposed_object_name [ , <table_hint> [ , ] ...n ] ]

将指定的表提示应用到与 exposed_object_name 对应的表或视图。 我们建议仅在计划指南的上下文中将表提示用作查询提示。

exposed_object_name 可以是下面的引用之一:

  • 当对查询的 FROM 子句中的表或视图使用别名时,exposed_object_name 就是别名。

  • 不使用别名时, exposed_object_name 与子句中 FROM 引用的表或视图完全匹配。 例如,如果使用由两部分组成的名称引用表或视图,则 exposed_object_name 就是这个由两部分组成的名称。

如果在指定 exposed_object_name 时未指定表提示,在查询中指定为属于对象的表提示的任何索引都会遭忽略。 然后,查询优化器确定索引使用情况。 当无法修改原始查询时,可以使用此方法消除表提示的效果 INDEX 。 请参阅 示例 J

<table_hint>

NOEXPAND [ , INDEX ( index_value [ ,...n ] | |INDEX = (index_value) ] |INDEX (index_value [ ,...n ] | |INDEX = (index_value) |FORCESEEK [ ( index_value ( index_column_name [,... ] ) ] | |FORCESCAN |HOLDLOCK |NOLOCK |NOWAIT |PAGLOCK |READCOMMITTED |READCOMMITTEDLOCK |READPAST |READUNCOMMITTED |REPEATABLEREAD |ROWLOCK |SERIALIZABLE |SNAPSHOT |SPATIAL_WINDOW_MAX_CELLS = integer_value |TABLOCK |TABLOCKX |UPDLOCK |XLOCK

要应用于作为查询提示exposed_object_name的表或视图的表提示。 有关这些提示的说明,请参阅 表提示

除其他表提示外INDEXFORCESCAN,不允许FORCESEEK作为查询提示,除非查询已有指定WITH表提示的子句。 有关详细信息,请参阅“备注”部分

注意

FORCESEEK使用参数进行指定会限制查询优化器可以考虑的计划数,而不是在指定FORCESEEK不使用参数时考虑的计划数。 这可能导致在更多情况下出现“无法生成计划”错误。

FOR TIMESTAMP AS OF 'point_in_time'

适用于:Microsoft Fabric 中的仓库

使用 OPTION 子句中的 TIMESTAMP 语法,查询过去存在的数据,这是 Microsoft Fabric Synapse 数据仓库中的一部分时间旅行功能。

yyyy-MM-ddTHH:mm:ss[.fff] 格式指定 point_in_time,返回当时显示的数据。 时区始终采用 UTC 格式。 使用 CONVERT 语法来获取样式 126 的必要日期时间格式。

TIMESTAMP AS OF 提示只能使用 OPTION 子句指定一次。 有关更多信息,请参阅过去存在的查询数据

注解

查询提示不能在语句中 INSERT 指定,但语句中使用子句时 SELECT 除外。

只能在顶级查询中指定查询提示,不能在子查询指定。 将表提示指定为查询提示时,可以在顶级查询或子查询中指定提示。 但是,为子句中的TABLE HINTexposed_object_name指定的值必须与查询或子查询中公开的名称完全匹配。

将表提示指定为查询提示

建议INDEX仅在计划指南上下文中使用或FORCESCANFORCESEEK表提示作为查询提示。 如果无法修改原始查询(例如,由于它是第三方应用程序),就会发现计划指南很有用。 在编译和优化查询之前,计划指南中指定的查询提示将添加到查询中。 对于即席查询,仅在测试计划指南语句时使用 TABLE HINT 子句。 对于所有其他即席查询,建议仅将这些提示指定为表提示。

指定为查询提示时,INDEXFORCESCANFORCESEEK表提示对以下对象有效:

  • 视图
  • 索引视图
  • 公用表表达式(必须在结果集填充公共表表达式的语句中 SELECT 指定提示)
  • 动态管理视图 (DMV)
  • 命名子查询

可以为没有任何现有表提示的查询指定 INDEXFORCESCAN表提示和 FORCESEEK 表提示。 还可以使用它们分别替换查询中的现有INDEXFORCESCANFORCESEEK或提示。

除其他表提示外INDEXFORCESCAN,不允许FORCESEEK作为查询提示,除非查询已有指定WITH表提示的子句。 在这种情况下,还必须将匹配提示指定为查询提示。 使用 TABLE HINT 子句将 OPTION 匹配提示指定为查询提示。 此规范保留了查询语义。 例如,如果查询包含表提示NOLOCKOPTION则计划指南@hints参数中的子句还必须包含NOLOCK提示。 请参阅 示例 K

使用查询存储提示来指定提示

使用查询存储提示功能,可以对通过查询存储标识的查询强制执行提示,而无需更改代码。 使用 sys.sp_query_store_set_hints 存储过程对查询应用提示。 请参阅示例 N。

示例

A. 使用 MERGE JOIN

以下示例指定 MERGE JOIN 在查询中运行 JOIN 操作。 该示例使用 AdventureWorks2022 数据库。

SELECT *
FROM Sales.Customer AS c
INNER JOIN Sales.CustomerAddress AS ca ON c.CustomerID = ca.CustomerID
WHERE TerritoryID = 5
OPTION (MERGE JOIN);
GO

B. 使用 OPTIMIZE FOR

以下示例指示查询优化器在优化查询时对 @city_name 使用值 'Seattle',并对 @postal_code 的所有列值使用谓词的平均选择性。 该示例使用 AdventureWorks2022 数据库。

CREATE PROCEDURE dbo.RetrievePersonAddress
@city_name NVARCHAR(30),
@postal_code NVARCHAR(15)
AS
SELECT * FROM Person.Address
WHERE City = @city_name AND PostalCode = @postal_code
OPTION ( OPTIMIZE FOR (@city_name = 'Seattle', @postal_code UNKNOWN) );
GO

C. 使用 MAXRECURSION

MAXRECURSION 可用于防止格式不佳的递归公共表表达式进入无限循环。 下面的示例特意创建了一个无限循环,然后使用 MAXRECURSION 提示将递归级别限制为两级。 该示例使用 AdventureWorks2022 数据库。

--Creates an infinite loop
WITH cte (CustomerID, PersonID, StoreID) AS
(
    SELECT CustomerID, PersonID, StoreID
    FROM Sales.Customer
    WHERE PersonID IS NOT NULL
  UNION ALL
    SELECT cte.CustomerID, cte.PersonID, cte.StoreID
    FROM cte
    JOIN  Sales.Customer AS e
        ON cte.PersonID = e.CustomerID
)
--Uses MAXRECURSION to limit the recursive levels to 2
SELECT CustomerID, PersonID, StoreID
FROM cte
OPTION (MAXRECURSION 2);
GO

更正编码错误后, MAXRECURSION 不再需要。

D. 使用 MERGE UNION

以下示例使用 MERGE UNION 查询提示。 该示例使用 AdventureWorks2022 数据库。

SELECT *
FROM HumanResources.Employee AS e1
UNION
SELECT *
FROM HumanResources.Employee AS e2
OPTION (MERGE UNION);
GO

E. 使用 HASH GROUP 和 FAST

以下示例使用 HASH GROUPFAST 查询提示。 该示例使用 AdventureWorks2022 数据库。

SELECT ProductID, OrderQty, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
WHERE UnitPrice < $5.00
GROUP BY ProductID, OrderQty
ORDER BY ProductID, OrderQty
OPTION (HASH GROUP, FAST 10);
GO

F. 使用 MAXDOP

以下示例使用 MAXDOP 查询提示。 该示例使用 AdventureWorks2022 数据库。

SELECT ProductID, OrderQty, SUM(LineTotal) AS Total
FROM Sales.SalesOrderDetail
WHERE UnitPrice < $5.00
GROUP BY ProductID, OrderQty
ORDER BY ProductID, OrderQty
OPTION (MAXDOP 2);
GO

G. 使用 INDEX

以下示例使用 INDEX 提示。 第一个示例指定了一个索引。 第二个示例为单个表引用指定多个索引。 在这两个示例中,由于对使用别名的表应用 INDEX 提示,因此 TABLE HINT 子句还必须指定与公开的对象名称相同的别名。 该示例使用 AdventureWorks2022 数据库。

EXEC sp_create_plan_guide
    @name = N'Guide1',
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 2;',
    @type = N'SQL',
    @module_or_batch = NULL,
    @params = NULL,
    @hints = N'OPTION (TABLE HINT(e, INDEX (IX_Employee_ManagerID)))';
GO
EXEC sp_create_plan_guide
    @name = N'Guide2',
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 2;',
    @type = N'SQL',
    @module_or_batch = NULL,
    @params = NULL,
    @hints = N'OPTION (TABLE HINT(e, INDEX(PK_Employee_EmployeeID, IX_Employee_ManagerID)))';
GO

H. 使用 FORCESEEK

以下示例使用 FORCESEEK 表提示。 该 TABLE HINT 子句还必须指定与公开的对象名称相同的两部分名称。 在对使用两部分名称的表应用 INDEX 提示时指定名称。 该示例使用 AdventureWorks2022 数据库。

EXEC sp_create_plan_guide
    @name = N'Guide3',
    @stmt = N'SELECT c.LastName, c.FirstName, HumanResources.Employee.Title
              FROM HumanResources.Employee
              JOIN Person.Contact AS c ON HumanResources.Employee.ContactID = c.ContactID
              WHERE HumanResources.Employee.ManagerID = 3
              ORDER BY c.LastName, c.FirstName;',
    @type = N'SQL',
    @module_or_batch = NULL,
    @params = NULL,
    @hints = N'OPTION (TABLE HINT( HumanResources.Employee, FORCESEEK))';
GO

I. 使用多个表提示

以下示例将 INDEX 提示应用于一个表,并将 FORCESEEK 提示应用于另一个表。 该示例使用 AdventureWorks2022 数据库。

EXEC sp_create_plan_guide
    @name = N'Guide4',
    @stmt = N'SELECT e.ManagerID, c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 3;',
    @type = N'SQL',
    @module_or_batch = NULL,
    @params = NULL,
    @hints = N'OPTION (TABLE HINT (e, INDEX( IX_Employee_ManagerID))
                       , TABLE HINT (c, FORCESEEK))';
GO

J. 使用 TABLE HINT 覆盖现有的表提示

以下示例演示如何使用 TABLE HINT 提示。 可以使用提示而不指定提示来替代 INDEX 在查询子句中指定的 FROM 表提示行为。 该示例使用 AdventureWorks2022 数据库。

EXEC sp_create_plan_guide
    @name = N'Guide5',
    @stmt = N'SELECT e.ManagerID, c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e WITH (INDEX (IX_Employee_ManagerID))
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 3;',
    @type = N'SQL',
    @module_or_batch = NULL,
    @params = NULL,
    @hints = N'OPTION (TABLE HINT(e))';
GO

K. 指定语义影响的表提示

以下示例在查询中包含两个表提示: NOLOCK即语义影响,以及 INDEX非语义影响。 若要保留查询的语义,在 NOLOCK 计划指南的子句中 OPTIONS 指定提示。 除了 NOLOCK 提示,指定 INDEX 提示 FORCESEEK ,并在语句编译和优化期间替换查询中的非语义影响 INDEX 提示。 该示例使用 AdventureWorks2022 数据库。

EXEC sp_create_plan_guide
    @name = N'Guide6',
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e
                   WITH (NOLOCK, INDEX (PK_Employee_EmployeeID))
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 3;',
    @type = N'SQL',
    @module_or_batch = NULL,
    @params = NULL,
    @hints = N'OPTION (TABLE HINT (e, INDEX(IX_Employee_ManagerID), NOLOCK, FORCESEEK))';
GO

下面的示例演示另一种保留查询语义并使优化器能够选择并非在表提示中指定的索引的方法。 允许优化器通过在子句中OPTIONS指定NOLOCK提示来选择。 指定提示是因为它会影响语义。 然后, TABLE HINT 仅指定包含表引用的关键字,并且没有 INDEX 提示。 该示例使用 AdventureWorks2022 数据库。

EXEC sp_create_plan_guide
    @name = N'Guide7',
    @stmt = N'SELECT c.LastName, c.FirstName, e.Title
              FROM HumanResources.Employee AS e
                   WITH (NOLOCK, INDEX (PK_Employee_EmployeeID))
              JOIN Person.Contact AS c ON e.ContactID = c.ContactID
              WHERE e.ManagerID = 2;',
    @type = N'SQL',
    @module_or_batch = NULL,
    @params = NULL,
    @hints = N'OPTION (TABLE HINT (e, NOLOCK))';
GO

L. 使用 USE HINT

以下示例使用 RECOMPILEUSE HINT 查询提示。 该示例使用 AdventureWorks2022 数据库。

SELECT * FROM Person.Address
WHERE City = 'SEATTLE' AND PostalCode = 98104
OPTION (RECOMPILE, USE HINT ('ASSUME_MIN_SELECTIVITY_FOR_FILTER_ESTIMATES', 'DISABLE_PARAMETER_SNIFFING'));
GO

M. 使用 QUERYTRACEON HINT

以下示例使用 QUERYTRACEON 查询提示。 该示例使用 AdventureWorks2022 数据库。 可以使用以下查询,为特定查询启用跟踪标志 4199 控制的所有影响计划的修补程序:

SELECT * FROM Person.Address
WHERE City = 'SEATTLE' AND PostalCode = 98104
OPTION (QUERYTRACEON 4199);

还可以使用多个跟踪标志,如以下查询中所示:

SELECT * FROM Person.Address
WHERE City = 'SEATTLE' AND PostalCode = 98104
OPTION  (QUERYTRACEON 4199, QUERYTRACEON 4137);

N. 使用查询存储提示

Azure SQL 数据库中的查询存储提示功能提供了一种易于使用的方法,可在不更改应用程序代码的情况下制定查询计划。

首先,标识已在查询存储目录视图中执行的查询,例如:

SELECT q.query_id, qt.query_sql_text
FROM sys.query_store_query_text qt
INNER JOIN sys.query_store_query q ON
    qt.query_text_id = q.query_text_id
WHERE query_sql_text like N'%ORDER BY ListingPrice DESC%'
  AND query_sql_text not like N'%query_store%';
GO

下面的示例应用了提示,对查询存储中标识的 query_id 39 强制执行旧版多重性估算器

EXEC sys.sp_query_store_set_hints @query_id= 39, @query_hints = N'OPTION(USE HINT(''FORCE_LEGACY_CARDINALITY_ESTIMATION''))';

以下示例应用提示,以强制实施最大内存授予大小(在配置的内存限制中PERCENTquery_id 39),该限制在查询存储中标识:

EXEC sys.sp_query_store_set_hints @query_id= 39, @query_hints = N'OPTION(MAX_GRANT_PERCENT=10)';

以下示例将多个查询提示应用于query_id 39,包括 RECOMPILEMAXDOP 1SQL Server 2012 (11.x) 查询优化器行为:

EXEC sys.sp_query_store_set_hints @query_id= 39,
    @query_hints = N'OPTION(RECOMPILE, MAXDOP 1, USE HINT(''QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_110''))';

O. 查询指定时间点的数据

适用于:Microsoft Fabric 中的仓库

使用 OPTION 子句中的 TIMESTAMP 语法,查询 Microsoft Fabric Synapse 数据仓库中过去存在的数据。 以下查询示例返回 2024 年 3 月 13 日下午 7:39:35.28 UTC 显示的数据。 时区始终采用 UTC 格式。

SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
ORDER BY OrderDateKey
OPTION (FOR TIMESTAMP AS OF '2024-03-13T19:39:35.28');--March 13, 2024 at 7:39:35.28 PM UTC