Azure SQL DB/DW 系列(11)——重新认识Query Store(4)——Query Store维护

本文属于Azure SQL DB/DW系列
上一文:Azure SQL DB/DW 系列(10)——重新认识Query Store(3)——配置查询存储
功能开启后,当然需要维护和监控,本文介绍Query Store的维护。

简介

  在我们使用Query Store的过程中,会出现不少问题,比如Query Store的状态,可能因为某些原因比如空间已满导致从READ_WRITE变成READ_ONLY甚至ERROR。这个时候就要去了解发生了什么。然后进行修复。
  另外你也需要去监控空间的使用率,从而判断收集和保存的间隔是否合理。
  还有就是计划强制是否成功。
  最后就行定期清理。

应对措施

监控状态

  首先,维护Query Store要了解其当前状态,可以用下面SQL 来查看,检查查询存储所需的操作模式(desired_state)和查询存储的操作模式(actual_state)是否一致:

SELECT DB_NAME() database_name,
actual_state_desc,
desired_state_desc
FROM sys.database_query_store_options
WHERE desired_state_desc <> actual_state_desc

  如果你需要检查全部数据库,可以用:

DECLARE @SQL NVARCHAR(MAX) = N'';
SELECT @SQL += REPLACE(REPLACE(N'USE [{{DBName}}];
SELECT
"{{DBName}}" database_name,
actual_state_desc,
desired_state_desc
FROM {{DBName}}.sys.database_query_store_options
WHERE desired_state_desc <> actual_state_desc '
,'{{DBName}}', [name])
,'"', "")
FROM sys.databases
WHERE is_query_store_on = 1
ORDER BY [name];
EXEC (@SQL);

  如果发现从READ_WRITE变成了READ_ONLY,可能会有很多原因导致,这些原因会存储到这个视图的readonly_reason列,其中的说明有:

  • 1 -数据库处于只读模式
  • 2 -数据库处於单用户模式
  • 4 -数据库处于紧急模式
  • 8 -数据库为辅助副本(适用于 Always On 和Azure SQL 数据库异地复制)。 只能在可读辅助副本上有效观察此值
  • 65536 -查询存储已达到 MAX_STORAGE_SIZE_MB 选项设置的大小限制。
  • 131072 -查询存储中的不同语句数已达到内部内存限制。 请考虑删除不需要的查询或升级到更高的服务层,以允许将查询存储传输到读写模式。适用对象: Azure SQL 数据库。
  • 262144 -等待保留在磁盘上的内存中项的大小已达到内部内存限制。 查询存储将暂时处于只读模式,直到内存中的项保留在磁盘上。适用对象: Azure SQL 数据库。
  • 524288 -数据库已达到磁盘大小限制。 查询存储是用户数据库的一部分,因此,如果数据库没有更多的可用空间,这意味着查询存储不能再进一步增长。适用对象: Azure SQL 数据库。

  找到原因之后,就要考虑修复,从2017开始,有可能在手动强制计划或者自动计划回归修正的时候出现潜在的性能问题,对于这个情况,一般尝试把Query Store设为OFF,然后改回READ_WRITE。如果不行,那就尝试运行sys.sp_query_store_consistency_check。然后清空Query Store里面的数据。下面是一个修复全部数据库的脚本:

DECLARE @SQL AS NVARCHAR(MAX) = N'';

SELECT @SQL += REPLACE(
		N'USE [{{DBName}}]
--Try Changing to READ_WRITE
IF EXISTS (SELECT * FROM sys.database_query_store_options
WHERE actual_state=3)
BEGIN
BEGIN TRY
ALTER DATABASE [{{DBName}}] SET QUERY_STORE =
OFF
ALTER DATABASE [{{DBName}}] SET QUERY_STORE =
READ_WRITE
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
END
--Run sys.sp_query_store_consistency_check
IF EXISTS (SELECT * FROM sys.database_query_store_options
WHERE actual_state=3)
BEGIN
BEGIN TRY
EXEC
[{{DBName}}].sys.sp_query_store_consistency_check
ALTER DATABASE [{{DBName}}] SET QUERY_STORE =ON
ALTER DATABASE [{{DBName}}] SET QUERY_STORE
(OPERATION_MODE = READ_WRITE)
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
END
--Run purge Query Store
IF EXISTS (SELECT * FROM sys.database_query_store_options
WHERE actual_state=3)
BEGIN
BEGIN TRY
ALTER DATABASE [{{DBName}}] SET QUERY_STORE
CLEAR
ALTER DATABASE [{{DBName}}] SET QUERY_STORE
(OPERATION_MODE = READ_WRITE)
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage
END CATCH;
END
'
		, '{{DBName}}', [name])
FROM sys.databases
WHERE is_query_store_on = 1;

EXEC (@SQL);

监控空间使用

  默认情况,当Query Store达到90%的空间使用率,会把空间清理到80%。如果MAX_STORAGE_SIZE_MB设置得太小,同时事务由很多,那么Query Store会增长得远超过最大大小的定义。下面脚本是监控实例中超过90%的数据库:

USE [<Database>];
GO
SELECT current_storage_size_mb,
max_storage_size_mb,
FROM sys.database_query_store_options
WHERE CAST(CAST(current_storage_size_mb AS
DECIMAL(21, 2)) / CAST(max_storage_size_mb AS
DECIMAL(21, 2)) * 100 AS DECIMAL(4, 2)) >= 90
AND size_based_cleanup_mode_desc = 'OFF';

  出现这种情况的话,可以使用下面两种方法之一来清理:

ALTER DATABASE [<Database Name>] SET QUERY_STORE CLEAR ALL;

  或者

USE [<Database>];
GO
EXEC sys.sp_query_store_flush_db;

计划强制失败

  由于索引变化, Hints等原因导致计划强制操作失败,这个时候可以先检查原因,可以使用T-SQL:

SELECT plan_id,
force_failure_count,
last_force_failure_reason
FROM sys.query_store_plan

也可以使用扩展事件:

CREATE EVENT SESSION [QueryStore_Forcing_Plan_Failure]
ON SERVER
ADD EVENT qds.query_store_plan_forcing_failed
ADD TARGET package0.ring_buffer WITH
(
MAX_MEMORY=4096 KB,
EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY=30 SECONDS,
MAX_EVENT_SIZE=0 KB,
MEMORY_PARTITION_MODE=NONE,
TRACK_CAUSALITY=OFF,
STARTUP_STATE=ON
);

  如果发现了有失败的计划,只需要在Query Store中移除这个计划,移除之后,其运行时统计信息也会一并移除。

EXECUTE sys.sp_query_store_remove_plan @plan_id = <plan_id>;

重置执行计划的统计信息

  sys.sp_query_store_reset_exec_stats可以清除特定计划的运行时统计信息,但是会保留执行计划。

USE [<Database>];
GO
EXECUTE sys.sp_query_store_reset_exec_stats @plan_id = <plan_id>;

  接下来开始介绍Query Store的报表,这个是Query Store展现给用户的结果,读懂和使用好它们才能算会用Query Store了。不过由于报表比较多,所以分几篇文章介绍。
  下一文:Azure SQL DB/DW 系列(12)——使用Query Store(1)——报表介绍(1)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章