提示 (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 ] ] )
}

<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

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

{ MERGE | HASH | CONCAT } UNION

指定所有 UNION 运算都通过合并、哈希或串联 UNION 集来运行。 如果指定了多个 UNION 提示,查询优化器就会从这些指定的提示中选择开销最少的策略。

{ LOOP | MERGE | HASH } JOIN

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

如果在同一查询对特定表对的 FROM 子句中指定联接提示,那么在联接两个表时优先使用此联接提示。 不过,仍必须遵循查询提示。 表对的联接提示只能限制在查询提示中选择允许的联接方法。 有关详细信息,请参阅联接提示 (Transact-SQL)

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 部分中的视图(包括 INSERT、UPDATE、MERGE 和 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

强制或禁用在 SQL Server 2019 大数据群集中使用外部表的 PolyBase 查询的横向扩展执行。 仅使用 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 数据库。

所配置的内存限制的最大内存授予大小(以百分比表示)。 如果查询在用户定义的资源池中运行,则保证查询不超过此限制。 在此情况下,如果查询没有所需的最小内存,系统将引发错误。 如果查询在系统池中运行(默认),则它至少会获得运行所需的内存。 如果 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 数据库。

最小内存授予大小所占配置的内存限制的百分比。 查询保证会获取 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 超出使用资源调控器配置的值,数据库引擎会使用资源调控器 MAXDOP 值(如 ALTER WORKLOAD GROUP (Transact-SQL) 中所述)。 使用 MAXDOP 查询提示时,所有和“最大并行度”配置选项一起使用的语义规则均适用。 有关详细信息,请参阅 配置 max degree of parallelism 服务器配置选项

警告

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

MAXRECURSION <integer_value>

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

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

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

有关详细信息,请参阅 WITH common_table_expression (Transact-SQL)

NO_PERFORMANCE_SPOOL

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

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

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

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

  • @variable_name

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

  • 未知

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

  • <literal_constant>

    要分配给 @variable_name 的文本常量值,以用于 OPTIMIZE 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 查询提示,用于覆盖 PARAMETERIZATION 数据库 SET 选项的当前设置。 无法直接在查询中指定它。

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

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

QUERYTRACEON <integer_value>

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

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

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

RECOMPILE

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

RECOMPILE 是创建存储过程的实用替代方法。 如果必须仅重新编译存储过程中的一部分查询,而不是重新编译整个存储过程,RECOMPILE 使用 WITH 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;与 SQL Server 2014 (12.x) 或更高版本的基数估计模型一起使用时,它等效于跟踪标志 9471。

  • '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(从 SQL Server 2017 (14.x) 开始)和 Azure SQL 数据库

  • 'DISABLE_BATCH_MODE_MEMORY_GRANT_FEEDBACK'

    禁用批处理模式内存授予反馈。 有关详细信息,请参阅批处理模式内存授予反馈

    适用范围:SQL Server(从 SQL Server 2017 (14.x) 开始)和 Azure SQL 数据库

  • 'DISABLE_DEFERRED_COMPILATION_TV'

    禁用表变量延迟编译。 有关详细信息,请参阅表变量延迟编译

    适用于:SQL Server(从 SQL Server 2019 (15.x) 开始)和 Azure SQL 数据库

  • 'DISABLE_INTERLEAVED_EXECUTION_TVF'

    对多语句表值函数禁用交错执行。 有关详细信息,请参阅多语句表值函数的交错执行

    适用范围:SQL Server(从 SQL Server 2017 (14.x) 开始)和 Azure SQL 数据库

  • 'DISABLE_OPTIMIZED_NESTED_LOOP'

    指示查询处理器在生成查询计划时不对优化的嵌套循环联接使用排序操作(批处理排序)。 此提示名与跟踪标志 2340 等效。

  • '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(从 SQL Server 2019 (15.x) 开始)和 Azure SQL 数据库

  • 'DISABLE_TSQL_SCALAR_UDF_INLINING'

    禁用标量 UDF 内联。 有关详细信息,请参阅标量 UDF 内联

    适用范围:SQL Server(从 SQL Server 2019 (15.x) 开始)和 Azure SQL 数据库

  • 'DISALLOW_BATCH_MODE'

    禁用批处理模式执行。 有关详细信息,请参阅执行模式

    适用范围:SQL Server(从 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'

    强制查询优化器行为在查询级别发生。 此行为就像使用数据库兼容性级别 n 编译查询,其中,n 是受支持的数据库兼容性级别(例如,100、130 等)。 请参阅 sys.dm_exec_valid_use_hints,以了解目前对 n 支持的值。

    适用于:SQL Server(从 SQL Server 2017 (14.x) CU10 开始)和 Azure SQL 数据库

    注意

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

  • 'QUERY_PLAN_PROFILE'

    启用用于查询的轻型分析。 当包含此新提示的查询完成时,会触发一个新扩展事件:query_plan_profile。 此扩展事件公开执行统计信息和实际执行计划 XML,类似于 query_post_execution_showplan 扩展事件,但仅针对包含新提示的查询。

    适用于:SQL Server(从 SQL Server 2016 (13.x) SP2 CU3 和 SQL Server 2017 (14.x) CU11 开始)。

    注意

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

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

提示

提示名称不区分大小写。

重要

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

USE PLAN N'<xml_plan>'

强制查询优化器对查询使用由 '<xml_plan>' 指定的现有查询计划。 无法使用 INSERT、UPDATE、MERGE 或 DELETE 语句来指定 USE PLAN。

此功能强制生成的执行计划与所强制执行的计划相同或类似。 由于生成的计划可能与 U标准版 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>) |FORCE标准版EK [(index_value(<<index_column_name> [,...> ] ) ] |FORCESCAN |HOLDLOCK |NOLOCK |NOWAIT |PAGLOCK |READCOMMITTED |READCOMMITTEDLOCK |READPAST |READUNCOMMITTED |REPEATABLEREAD |ROWLOCK |标准版RIALIZABLE |SNAPSHOT |SPATIAL_WINDOW_MAX_CELLS = <integer_value> |TABLOCK |TABLOCKX |UPDLOCK |XLOCK

要作为查询提示应用于与 exposed_object_name 对应的表或视图的表提示。 有关这些提示的说明,请参阅表提示 (Transact-SQL)

不允许将非 INDEX、FORCESCAN 和 FORCESEEK 的表提示用作查询提示,除非该查询已经具有一个指定该表提示的 WITH 子句。 有关详细信息,请参阅“备注”部分

注意

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

备注

无法在 INSERT 语句中指定查询提示,除非在语句中使用了 SELECT 子句。

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

将表提示指定为查询提示

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

如果将 INDEX、FORCESCAN 和 FORCESEEK 表提示指定为查询提示,它们会对以下对象有效:

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

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

不允许将非 INDEX、FORCESCAN 和 FORCESEEK 的表提示用作查询提示,除非该查询已经具有一个指定该表提示的 WITH 子句。 在这种情况下,还必须将匹配提示指定为查询提示。 在 OPTION 子句中使用 TABLE HINT,将匹配提示指定为查询提示。 此规范保留了查询语义。 例如,如果查询包含表提示 NOLOCK,则计划指南的 @hints 参数中的 OPTION 子句必须也包含 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 GROUP 和 FAST 查询提示。 该示例使用 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 提示。 使用提示时,可以不指定提示替代在查询的 FROM 子句中指定的 INDEX 表提示行为。 该示例使用 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 这两个表提示,其中前者会影响语义,后者不影响语义。 若要保留查询的语义,应在计划指南的 OPTIONS 子句中指定 NOLOCK 提示。 与 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 提示来进行选择。 指定提示是因为它会影响语义。 然后,指定只有表引用而无 INDEX 提示的 TABLE HINT 关键字。 该示例使用 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

以下示例使用 RECOMPILE 和 USE 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''))';

下面的示例应用了提示,对查询存储中标识的 query_id 39 强制执行了配置内存限制 PERCENT 的最大内存授予大小:

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

下面的示例向 query_id 39 应用了多个查询提示,包括RECOMPILE、MAXDOP 1 和 SQL 2012 查询优化器行为:

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