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)

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