如何导出查询存储数据?

Jam*_*ins 6 sql-server query-store sql-server-2017

我在 SQL 2017 实例上运行了查询存储 (QS)。目前在 RTM 中,RTM CU13 目前正在测试中,将在下个月的补丁窗口中应用于 prod。

虽然大多数查询和报告快速返回结果,几乎没有影响,但我尝试查看等待的任何事情都是有问题的。CPU 使用率从 20% 上升到 80%,并在那里停留几分钟,直到我杀死它。这是 24/7 生产系统,所以如果我真的想查看 QS 等待,我将需要在其他地方进行。

数据库为 150GB,其中 1000MB 空间用于 QS。我有一个有 10GB 空间的沙箱,所以如果我能把 QS 数据拿出来,我就可以在那里玩。

我环顾四周,我没有找到如何做到这一点。我发现的最好的是这篇sql.sasquatch 2016 post with an 2016 answer by Erin Stellato

目前没有导出和/或导入查询存储数据的选项,但有一个 Connect 项目可以投票:https : //connect.microsoft.com/SQLServer/feedback/details/2620017/export-query-store -tables-separately-from-the-database-tables

注意:链接转到重定向“Microsoft Connect 已停用”看起来实际链接应该是https://feedback.azure.com/forums/908035-sql-server/suggestions/32901670-export-query-store -表与数据分开

看看 Microsoft,我发现您可能用来访问数据的大多数东西都是视图、存储过程或报告。我没有看到从数据库中提取所有 QS 内容的方法。

直接查询的示例,使用视图示例 Kendra Little我曾想过从Select *视图中执行一个并将结果导出到我的沙箱的想法。但由于我没有找到任何人谈论它,我不确定这是个好主意。

有关的

此外, 我希望能够保留 CU13 之前的查询存储结果,以用作比较 CU13 之后的基线。

在第一个回答后编辑并编辑相同的 最近编辑 jadarnel27 对答案的编辑添加了很好的信息,但我不关心用户界面,我希望能够在不更改数据库或影响性能的情况下查询数据。作为次要目标,我希望能够存档 QS 数据,以便我可以查看以前的性能(即在升级之前,但在旧的 QS 数据会被清除之后)

Jos*_*ell 8

首先,通过更新统计信息、添加带有计划指南的查询提示或更改数据库兼容性级别/CE,您可能能够通过直接针对查询存储目录视图的查询获得可接受的性能。在此处查看 Forrest 和 Marian 的回答:

永无止境的查询存储搜索


如果您使用的是 SP1 或更高版本,最简单的方法是使用DBCC CLONEDATABASE- 其中包括统计信息、查询存储数据和模式对象 - 但没有来自表的实际数据


否则,对于导出,一种方法是SELECT...INTO从查询存储视图到“沙箱”数据库的简单方法。 以上是相关意见

基本方法是这样的:

SELECT * INTO Sandbox.dbo.query_store_runtime_stats FROM sys.query_store_runtime_stats;
SELECT * INTO Sandbox.dbo.query_store_runtime_stats_interval FROM sys.query_store_runtime_stats_interval;
SELECT * INTO Sandbox.dbo.query_store_plan FROM sys.query_store_plan;
SELECT * INTO Sandbox.dbo.query_store_query FROM sys.query_store_query;
SELECT * INTO Sandbox.dbo.query_store_query_text FROM sys.query_store_query_text;
SELECT * INTO Sandbox.dbo.query_store_wait_stats FROM sys.query_store_wait_stats;
Run Code Online (Sandbox Code Playgroud)

这种方法的好处在于:

  • 你只会得到你需要的数据 (1000 MB)
  • 您可以添加索引来支持您的报告查询,因为这些是实际表
  • 它们不会有导致实际视图性能不佳的异常内存扫描行为(再次因为它们是实际表)
    • 注意:SELECT...INTO查询不应像内置查询存储报告查询那样驱动 CPU,因为它们不会有导致重复访问内存中 TVF 的问题连接
  • 您可以通过更改表名或在表中添加一列指示用于该导入的数据和/或 SQL Server 版本来保留不同版本的数据(针对不同的 CU 级别等)

这种方法的“缺点”是您不能使用查询存储用户界面。一种解决方法是使用分析器或扩展事件来捕获用户界面为您需要的特定报告执行的查询。您甚至可以在非生产环境中执行此捕获,因为查询应该相同。


警告:这可能是一个非常糟糕的主意。 您通常无法写入这些表是有原因的。特别感谢Forrest向我提到这种可能性。

如果您真的希望能够使用用户界面,您实际上可以在通过 DAC 连接时加载基本查询存储表的数据。这对我有用。

提醒:您必须使用 DAC 连接来执行此操作,否则您将收到与sys.plan_persist_*表不存在相关的错误

USE [master];
GO
CREATE DATABASE [Sandbox];
GO

USE [YourSourceDatabaseWithTheQueryStoreInfo];
GO

BEGIN TRANSACTION;

INSERT INTO Sandbox.sys.plan_persist_runtime_stats SELECT * FROM sys.plan_persist_runtime_stats;
INSERT INTO Sandbox.sys.plan_persist_runtime_stats_interval SELECT * FROM sys.plan_persist_runtime_stats_interval;
INSERT INTO Sandbox.sys.plan_persist_plan SELECT * FROM sys.plan_persist_plan;
INSERT INTO Sandbox.sys.plan_persist_query SELECT * FROM sys.plan_persist_query;
INSERT INTO Sandbox.sys.plan_persist_query_text SELECT * FROM sys.plan_persist_query_text;
INSERT INTO Sandbox.sys.plan_persist_wait_stats SELECT * FROM sys.plan_persist_wait_stats;
INSERT INTO Sandbox.sys.plan_persist_context_settings SELECT * FROM sys.plan_persist_context_settings

COMMIT TRANSACTION;
GO

USE [master];
GO
ALTER DATABASE [Sandbox] SET QUERY_STORE = ON (OPERATION_MODE = READ_ONLY);
Run Code Online (Sandbox Code Playgroud)

注意:如果您使用的是 SQL Server 2016,则需要删除有关等待统计信息的行 - 该目录视图直到 SQL Server 2017 才添加

这样做之后,我能够使用 SSMS 中的查询存储 UI 查看来自源数据库的查询信息。整洁的!

在 Query Store off 的情况下将数据加载到 Sandbox 数据库中,然后在只读模式下打开 Query Store,这一点很重要 否则 QS 最终会处于错误状态,并将其写入 SQL Server 错误日志:

错误:12434,严重性:20,状态:56
。数据库沙箱中的查询存储无效,可能是由于架构或目录不一致。

处于“错误”状态的查询存储

我还注意到,如果源数据库中有内存中 OLTP (Hekaton) 表,这将不起作用。无论我做什么,查询存储最终都会处于“错误”状态,并在错误日志中显示以下消息:

错误:5571,严重性:16,状态:2。
内部 FILESTREAM 错误:无法访问垃圾收集表。

您可以通过向 Sandbox 数据库添加内存优化文件组来解决这个问题,我还没有尝试过。