Azure SQL DB/DW 系列(6)——Query Store案例(3)——查看等待信息

本文属于Azure SQL DB/DW系列
上一文:Azure SQL DB/DW 系列(5)——Query Store案例(2)——计划回归
本文演示如何用Query Store查看等待信息

前言

  关于等待信息的查看和使用方式有很多种,本文用全新的方法也就是Query Store来查看等待信息。
  我们知道,等待信息几乎可以说是常规应对性能问题甚至其他异常时的首要切入点。其实回顾过去的等待信息,它本身也在不停发展,比如sys.dm_os_wait_statistics和sys.dm_os_waiting_tasks这两个过去非常重要的DMV之外,从2016开始又引入了sys.dm_exec_session_wait_stats,用于提供关于正在活动的会话的等待信息。
  从SQL 2016 SP1开始,等待信息也开始存在于实际执行计划中。但是执行计划的内容通常还是比较难准确有效地捕获的,所以我们可以使用Query Store,上一文也演示过关于执行计划在Query Store中的使用,所以我们可以用类似的方式来获取等待信息。

环境准备

  这次使用WideWorldImporters作为测试,如果像我现在使用Linux上的SQL Server,可以参考我的文章里面的方法下载:SQL Server On Linux(3)——SQL Server 2019 For Linux 下载并部署示例数据库,下面是我用的下载文件命令:

wget -O /tmp/WideWorldImporters-Full.bak "https://github.com/Microsoft/sql-server-samples/releases/download/wide-world-importers-v1.0/WideWorldImporters-Full.bak"

  下载完成之后,就还原到我的数据库中,过程就不演示了。下面对这个库修改兼容级别到2019(150)并开启Query Store,然后做简单的配置,如果要反复实验,可以用脚本中的第四部分来清空Query Store:

USE [master]
GO
ALTER DATABASE [WideWorldImporters] SET COMPATIBILITY_LEVEL = 150
GO

ALTER DATABASE [WideWorldImporters] SET QUERY_STORE = ON;
GO
 
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE 
(
  OPERATION_MODE = READ_WRITE
);
GO
 --清空Query Store
ALTER DATABASE [WideWorldImporters] SET QUERY_STORE CLEAR;
GO

  然后创建一个存储过程,OPTION (QUERYTRACEON 8649)代表着强制执行并行运行:

use WideWorldImporters
GO
 
CREATE OR ALTER PROCEDURE [Sales].[OrderInfo]
AS
BEGIN
  WHILE 1=1
  BEGIN
    SELECT *
      FROM Sales.OrderLines ol
      INNER JOIN Warehouse.StockItems s
      ON ol.StockItemID = s.StockItemID
      OPTION (QUERYTRACEON 8649);
  END
END

获取信息

  接下来执行存储过程:exec [Sales].[OrderInfo],注意这是一个死循环的存储过程,几分钟之后手动停止。打开查询存储查看【资源消耗量最大的几个查询】,当然的,这里第一名的肯定是刚才的存储过程。
在这里插入图片描述
  默认情况下,这里显示的是“总持续时间”,我们可以在下图的【配置】中从【持续时间(ms)】改到【等待时间(ms)】:
在这里插入图片描述
  把鼠标移到柱状条上,可以看到等待状态的信息:
在这里插入图片描述
  在这个图上面很明显看出等待类型和它们的等待时间,是不是比过去的敲命令直观很多,而且这些还是语句级别的等待信息,在这里“Parallelism等待时间”是最久的。不过这篇文章不是讲解如何分析等待信息,而是介绍如何使用Query Store查看它们。
  当然还是有DMV来查询的,比如下面这个就是查看一个小时内的等待信息,可以调整数字来调控时间范围:

SELECT TOP (10)
  [ws].[wait_category_desc],
  [ws].[avg_query_wait_time_ms],
  [ws].[total_query_wait_time_ms],
  [ws].[plan_id],
  [qt].[query_sql_text],
  [rsi].[start_time],
  [rsi].[end_time]
FROM [sys].[query_store_query_text] [qt]
JOIN [sys].[query_store_query] [q]
    ON [qt].[query_text_id] = [q].[query_text_id]
JOIN [sys].[query_store_plan] [qp] 
    ON [q].[query_id] = [qp].[query_id]
JOIN [sys].[query_store_runtime_stats] [rs] 
    ON [qp].[plan_id] = [rs].[plan_id]
JOIN [sys].[query_store_runtime_stats_interval] [rsi] 
    ON [rs].[runtime_stats_interval_id] = [rsi].[runtime_stats_interval_id]
JOIN [sys].[query_store_wait_stats] [ws]
    ON [ws].[runtime_stats_interval_id] = [rs].[runtime_stats_interval_id]
    AND [ws].[plan_id] = [qp].[plan_id]
WHERE [rsi].[end_time] > DATEADD(MINUTE, -60, GETUTCDATE()) 
AND [ws].[execution_type] = 0
ORDER BY [ws].[avg_query_wait_time_ms] DESC;

小结

  本文又演示了一个Query Store的用法,当然都很简单,不过作为一个演示,我觉得已经足够让读者对Query Store引起兴趣。

下一文:Azure SQL DB/DW 系列(7)——

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