了解查询提示

已完成

查询提示是可用于强制执行查询处理器的选项或策略,用于在执行计划中对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)。

查询存储提示

查询存储提示 提供了一种简单的方法来调整查询计划,而无需修改应用程序代码。

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

查询存储提示如何运行的屏幕截图。

若要使用查询存储提示,需要标识查询语句的查询存储 query_id,你希望通过它查询存储目录视图、内置查询存储报告或 Azure SQL 数据库的 Query Performance Insight 修改。 然后,使用你想要应用于查询的 query_idsp_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,同时使数据库保持当前兼容性。

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