了解查询提示

已完成

查询提示是可用于强制执行查询处理器以在 SELECTINSERTUPDATEDELETE 语句的执行计划中使用特定运算符的选项或策略。 查询提示会覆盖查询处理器可能为具有 OPTION 子句的给定查询选择的任何执行计划。

在大多数情况下,查询优化器会根据索引、统计信息和数据分布选择有效的执行计划。 数据库管理员很少需要手动干预。

可以通过将查询提示添加到查询末尾来更改查询的执行计划。 例如,如果将 OPTION (MAXDOP <integer_value>) 添加到使用单个 CPU 的查询的末尾,则查询可能会使用多个 CPU(并行度),具体取决于所选值。 或者,可以使用 OPTION (RECOMPILE) 来确保每次执行查询时都会生成新的临时计划。

--With maxdop hint
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

--With recompile hint
SELECT City
FROM Person.Address
WHERE StateProvinceID=15 OPTION (RECOMPILE)
GO

尽管查询提示可能会为各种性能相关问题提供本地化解决方案,但出于以下原因,应避免在生产环境中使用这些解决方案。

  • 查询时拥有永久查询提示可能会导致结构数据库更改,这对该不适用查询非常有利。
  • 如果将查询绑定到特定执行计划,则无法从后续版本的 SQL Server 中的新功能和改进的功能中受益。

但是,SQL Server 中提供了多种查询提示,这些提示用于不同的用途。 接下来对其中几个进行讨论:

  • FAST <integer_value>—在继续执行查询时检索前 integer_value<> 行。 它对快速查询提示的小型数据集和低值更加有效。 随着行计数的增加,查询成本会更高。

  • OPTIMIZE FOR—提供有关查询优化器的说明,指示在编译和优化查询时应使用局部变量的特定值。

  • USE PLAN—查询优化器将使用由 xml_plan 属性指定的查询计划。

  • RECOMPILE—为查询创建新的临时计划,并在执行查询后立即放弃它。

  • { LOOP | MERGE | HASH } JOIN—指定所有联接操作都通过整个查询中的 LOOP JOINMERGE JOINHASH JOIN 执行。 如果指定多个联接提示,则优化器从选项中选择开销最少的联接策略。

  • MAXDOP <integer_value>—覆盖 sp_configure 的“最大并行度”值。 指定此选项的查询也会覆盖资源调控器。

还可以在同一查询中应用多个查询提示。 以下示例在同一查询中使用 HASH GROUPFAST <integer_value> 查询提示。

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    

若要了解有关查询提示的详细信息,请参阅提示 (Transact-SQL)

查询存储提示(预览版)

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

当查询优化器不生成有效的执行计划,以及开发人员或 DBA 无法修改原始查询文本时,查询存储提示非常有用。 在某些应用程序中,查询文本可能会被硬编码或自动生成。

Screenshot of how Query Store hints work.

若要使用查询存储提示,需要标识查询语句的查询存储 query_id,你希望通过它查询存储目录视图、内置查询存储报表或 Azure SQL 数据库的 Query Performance Insight 修改。 然后,使用你想要应用于查询的 query_id 和查询提示字符串执行 sp_query_store_set_hints

以下示例演示如何获取特定查询的 query_id,然后使用它向查询应用 RECOMPILEMAXDOP 提示。

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 CustomerName DESC%'  
  AND query_sql_text not like N'%query_store%'
GO

--Assuming the query_id returned by the previous query is 42
EXEC sys.sp_query_store_set_hints @query_id= 42, @query_hints = N'OPTION(RECOMPILE, MAXDOP 1)'
GO

在几种情况下,查询存储提示可以帮助解决查询级别性能问题。

  • 在每次执行时重新编译查询。
  • 限制统计信息更新操作的最大并行度。
  • 使用哈希联接而不是嵌套循环联接。
  • 对特定查询使用兼容性级别 110,同时将数据库保留为当前兼容性级别。

注意

SQL 托管实例也支持查询存储提示。

有关查询存储提示的详细信息,请参阅查询存储提示