SQL Server 使用 OPTION (RECOMPILE) 和查询存储的查询

设置
        我们正在使用 WideWorldImporters 数据库,您可以从 Github 下载【sql-server-samples/samples/databases/wide-world-importers at master · microsoft/sql-server-samples · GitHub】。我正在运行SQL Server 2017 的最新 CU【https://sqlserverbuilds.blogspot.com/】,但这适用于任何版本的查询存储(SQL Server 2016 及更高版本)和 Azure SQL 数据库。下面的代码将启用查询存储,将 QUERY_CAPTURE_MODE 设置为 ALL(要了解各种不同以及建议用于生产的内容,请查看我的查询存储设置帖子【https://blog.csdn.net/hefeng_aspnet/article/details/140130527】),然后清除查询存储中的所有内容。我通常不建议您清除查询存储,但我们正在恢复演示数据库,这是一个演示,所以我要确保我们从头开始。最后,我们将创建一个用于测试的存储过程,该存储过程使用 RECOMPILE 创建,然后完全释放过程缓存。请注意,我不建议向存储过程添加 RECOMPILE 选项 - 这意味着每次执行时都会重新编译整个存储过程。我也不建议在生产中释放过程缓存 - 这只是为了演示目的。
USE [master];
GO
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE = ON;
GO
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE (OPERATION_MODE = READ_WRITE, QUERY_CAPTURE_MODE = ALL);
GO
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE CLEAR;
GO
 
DROP PROCEDURE IF EXISTS Sales.usp_GetOrderInfo 
GO
 
CREATE PROCEDURE Sales.usp_GetOrderInfo
(@OrderID INT)
WITH RECOMPILE
AS
BEGIN
SELECT
o.OrderID,
o.CustomerID,
o.OrderDate,
ol.Quantity,
ol.UnitPrice
FROM Sales.Orders o
JOIN Sales.OrderLines ol
ON o.OrderID = ol.OrderID
WHERE o.OrderID = @OrderID;
END
GO
 
DBCC FREEPROCCACHE;
GO

测试
        首先,执行一个临时查询(不属于存储过程的一部分,具有 OPTION (RECOMIPLE) 提示):

SELECT
i.InvoiceID,
i.CustomerID,
i.InvoiceDate,
il.Quantity,
il.UnitPrice
FROM Sales.Invoices i
JOIN Sales.InvoiceLines il
ON i.InvoiceID = il.InvoiceID
WHERE i.InvoiceID = 54983
OPTION (RECOMPILE);
GO 10

如果我们检查计划缓存,您会注意到没有证据表明该查询已执行:

SELECT
qs.execution_count,
st.text, 
qs.creation_time
FROM sys.dm_exec_query_stats AS [qs] 
CROSS APPLY sys.dm_exec_sql_text ([sql_handle]) [st]
CROSS APPLY sys.dm_exec_query_plan ([plan_handle]) [p]
WHERE [st].[text][/text] LIKE '%Sales.Invoices%';
GO

但如果我们查看查询存储,我们确实会看到以下查询:
SELECT
[qsq].[query_id], 
[qsp].[plan_id],
[qsq].[object_id],
[rs].[count_executions],
[rs].[last_execution_time],
[rs].[avg_duration],
[rs].[avg_logical_io_reads],
[qst].[query_sql_text],
TRY_CONVERT(XML, [qsp].[query_plan]) AS [QueryPlan_XML],
[qsp].[query_plan] 
FROM [sys].[query_store_query] [qsq] 
JOIN [sys].[query_store_query_text] [qst]
ON [qsq].[query_text_id] = [qst].[query_text_id]
JOIN [sys].[query_store_plan] [qsp] 
ON [qsq].[query_id] = [qsp].[query_id]
JOIN [sys].[query_store_runtime_stats] [rs] 
ON [qsp].[plan_id] = [rs].[plan_id]
WHERE [qst].[query_sql_text] LIKE '%Sales.Invoices%';
GO 

如果我们展开 query_sql_text 列(由于空间原因删除了中间的文本),你会看到文本包含OPTION (RECOMPILE)。这很酷。

现在让我们执行使用 RECOMPILE 创建的存储过程,然后检查计划缓存:

EXEC Sales.usp_GetOrderInfo 57302;
GO 10
 
SELECT
qs.execution_count,
st.text, 
qs.creation_time
FROM sys.dm_exec_query_stats AS [qs] 
CROSS APPLY sys.dm_exec_sql_text ([sql_handle]) [st]
CROSS APPLY sys.dm_exec_query_plan ([plan_handle]) [p]
WHERE [st].[text][/text] LIKE '%Sales.Orders%';
GO

当我们检查查询存储时,我们确实看到了查询: 

SELECT
[qsq].[query_id], 
[qsp].[plan_id],
[qsq].[object_id],
OBJECT_NAME([qsq].[object_id]) AS ObjectName,
[rs].[count_executions],
[rs].[last_execution_time],
[rs].[avg_duration],
[rs].[avg_logical_io_reads],
[qst].[query_sql_text],
TRY_CONVERT(XML, [qsp].[query_plan]) AS [QueryPlan_XML],
[qsp].[query_plan] /* nvarchar(max) */
FROM [sys].[query_store_query] [qsq] 
JOIN [sys].[query_store_query_text] [qst]
ON [qsq].[query_text_id] = [qst].[query_text_id]
JOIN [sys].[query_store_plan] [qsp] 
ON [qsq].[query_id] = [qsp].[query_id]
JOIN [sys].[query_store_runtime_stats] [rs] 
ON [qsp].[plan_id] = [rs].[plan_id]
WHERE OBJECT_NAME([qsq].[object_id]) = 'usp_GetOrderInfo';
GO

概括
        无论在何处使用 OPTION(RECOMPILE)——在临时查询的语句级别还是在存储过程内的语句——以及在创建或执行期间在过程级别使用 RECOMPILE 选项时——查询文本、计划和执行统计信息仍会在查询存储中捕获。

参考:Queries with OPTION (RECOMPILE) and Query Store - Erin Stellato 

相关推荐

  1. SQLServer数据库查询语句

    2024-07-20 15:30:02       33 阅读
  2. SqlServer 查询表、视图、存储过程被哪些引用

    2024-07-20 15:30:02       40 阅读
  3. SQLServer基本查询

    2024-07-20 15:30:02       30 阅读
  4. sqlserver 表大小查询

    2024-07-20 15:30:02       28 阅读
  5. sqlserver2012 跨服务器查询

    2024-07-20 15:30:02       67 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-20 15:30:02       123 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-20 15:30:02       131 阅读
  3. 在Django里面运行非项目文件

    2024-07-20 15:30:02       109 阅读
  4. Python语言-面向对象

    2024-07-20 15:30:02       117 阅读

热门阅读

  1. 如何使用fiddler 查看手机端数据包

    2024-07-20 15:30:02       27 阅读
  2. AI艺术创作:掌握Midjourney和DALL-E的技巧与策略

    2024-07-20 15:30:02       27 阅读
  3. 快速创建 vue 项目并添加 Dockerfile 文件

    2024-07-20 15:30:02       23 阅读
  4. C语言(7.4)

    2024-07-20 15:30:02       30 阅读
  5. 怎么降低美国服务器硬盘故障率?

    2024-07-20 15:30:02       29 阅读
  6. 智能听诊器:居家宠物健康管理新助手

    2024-07-20 15:30:02       26 阅读
  7. Springboo3中使用虚线程

    2024-07-20 15:30:02       26 阅读
  8. C#面:MVC中的TempData\ViewBag\ViewData区别?

    2024-07-20 15:30:02       25 阅读