初涉SQL Server性能问题(2/4):列出等待资源的会话

原文:初涉SQL Server性能问题(2/4):列出等待资源的会话

初涉SQL Server性能问题(1/4)里,我们知道了如何快速检查服务器实例上正运行的任务数和IO等待的任务数。这个是轻量级的脚本,不会给服务器造成任何压力,即使服务器在高负荷下,也可以正常获得结果。

问题检测的第2步是获取在进行任何资源等待的会话。下面的脚本会帮助我们获得这些信息。这个查询需要预建立一个函数,如果会话是由SQL Server代理启动的话,会显示具体的作业名。

 1 /*****************************************************************************************
 2            PREREQUISITE FUNCTION
 3 ******************************************************************************************/
 4 USE MASTER
 5 GO
 6 CREATE FUNCTION ConvertStringToBinary  ( @hexstring  VARCHAR(100)
 7 )  RETURNS BINARY(34)  AS
 8 BEGIN
 9
10    RETURN(SELECT CAST(‘‘ AS XML).value(‘xs:hexBinary( substring(sql:variable("@hexstring"), sql:column("t.pos")) )‘, ‘varbinary(max)‘)
11    FROM (SELECT CASE SUBSTRING(@hexstring, 1, 2) WHEN ‘0x‘ THEN 3 ELSE 0 END) AS t(pos))
12 END
13 /***************************************************************************************
14 STEP 2: List the session which are currently waiting for resource
15 ****************************************************************************************/
16 SELECT node.parent_node_id AS Node_id,
17 es.HOST_NAME,
18 es.Login_name,
19 CASE WHEN es.program_name LIKE ‘%SQLAgent - TSQL JobStep%‘ THEN
20          (
21           SELECT ‘SQL AGENT JOB: ‘+name FROM msdb..sysjobs WHERE job_id=
22           MASTER.DBO.ConvertStringToBinary (LTRIM(RTRIM((SUBSTRING(es.program_name,CHARINDEX(‘(job‘,es.program_name,0)+4,35)))))
23           )
24     ELSE es.program_name END  AS [Program Name] ,
25 DB_NAME(er.database_id) AS DatabaseName,
26 er.session_id,
27 wt.blocking_session_id,
28 wt.wait_duration_ms,
29 wt.wait_type,
30 wt.NoThread ,
31 er.command,
32 er.status,
33 er.wait_resource,
34 er.open_transaction_count,
35 er.cpu_time,
36 er.total_elapsed_time AS ElapsedTime_ms,
37 er.percent_complete ,
38 er.reads,
39 er.writes,
40 er.logical_reads,
41 wlgrp.name AS ResoursePool              ,
42 SUBSTRING   (sqltxt.TEXT,(er.statement_start_offset/2) + 1,
43             ((CASE WHEN er.statement_end_offset = -1
44              THEN LEN(CONVERT(NVARCHAR(MAX), sqltxt.TEXT)) * 2
45              ELSE er.statement_end_offset
46             END - er.statement_start_offset)/2) + 1) AS [Individual Query],
47 sqltxt.TEXT AS [Batch Query]
48 FROM (SELECT session_id, SUM(wait_duration_ms) AS
49 wait_duration_ms,wait_type,blocking_session_id,COUNT(*) AS NoThread
50 FROM  SYS.DM_OS_WAITING_TASKS  GROUP BY session_id, wait_type,blocking_session_id) wt
51 INNER JOIN SYS.DM_EXEC_REQUESTS  er ON wt.session_id=er.session_id INNER JOIN SYS.DM_EXEC_SESSIONS es ON es.session_id= er.session_id
52 INNER JOIN SYS.DM_RESOURCE_GOVERNOR_WORKLOAD_GROUPS wlgrp ON wlgrp.group_id=er.group_id
53 INNER JOIN  (SELECT  os.parent_node_id ,task_address FROM SYS.DM_OS_SCHEDULERS  OS INNER JOIN
54 SYS.DM_OS_WORKERS  OSW ON OS.scheduler_address=OSW.scheduler_address
55 WHERE os.status=‘VISIBLE ONLINE‘ GROUP BY os.parent_node_id ,task_address ) node
56 ON node.task_address=er.task_address
57 CROSS APPLY SYS.DM_EXEC_SQL_TEXT(er.sql_handle) AS sqltxt
58 WHERE sql_handle IS NOT NULL AND wt.wait_type NOT IN (‘WAITFOR‘,‘BROKER_RECEIVE_WAITFOR‘)
59 GO

输出结果的每列说明介绍如下:

  • Node_id  NUMA节点ID。可以被调度者查询的节点映射。
  • HOST_NAME 建立连接的计算机名。
  • Login_name 连接到数据库服务器的会话用户名。
  • Program Name 使用会话的对应程序名。在连接字符串里可以设置程序名。如果会话是SQL Server代理的一部分,则显示作业名。
  • DatabaseName 会话的当前数据库名。
  • session_id 会话ID。
  • blocking_session_id 阻塞语句的会话ID。
  • wait_duration_ms 等待时间,单位为毫秒。这个时间不包括信号等待时间(signal wait time )。
  • wait_type 等待类型名称,例如:SLEEP_TASK,CXPACKET等。
  • NoThread 当前会话的线程数,如果当前会话是并行执行(parallel execution)的话。
  • command 标识当前类型的命令,即T-SQL语句,例如Select,insert,update,delete等。
  • status 请求状态:Background,Running,Runnable,Sleeping 和 Suspended。
  • wait_resource 请求当前等待的资源。
  • open_transaction_count 当前会话打开的事务数。
  • cpu_time 请求使用的CPU时间,单位毫秒。
  • ElapsedTime_ms 自请求到达后,占用的CPU时间,单位毫秒。
  • percent_complete 指定操作的工作完成进度,例如备份、还原、回滚等。
  • reads 请求执行的读数。
  • writes 请求执行的写数。
  • logical_reads 请求执行的逻辑读数。
  • ResoursePool 资源管理池名称。
  • Individual Query 在会话里运行的批处理SQL语句。
  • Batch Query 在会话里运行的批处理(存储过程/一系列的语句)。

上述查询多次执行后,输出结果有很长wait_duration_ms的会话,这个会话不被其他会话阻塞,且一直在输出结果里。我们就要看看这个会话的程序名,主机名,登录用户名,还有对应的执行语句,具体进行什么操作造成的。根据这些信息,我们可以选择性的去终止这个会话,然后分析下具体的执行语句。如果会话是被阻塞的,我们要用另外的语句来找出阻塞的会话。

第3步,列出服务器上正运行的会话清单。

 1 /***************************************************************************************
 2 STEP 3: List the session which are currently waiting/running
 3 ****************************************************************************************/
 4 SELECT node.parent_node_id AS Node_id,
 5 es.HOST_NAME,
 6 es.login_name,
 7 CASE WHEN es.program_name LIKE ‘%SQLAgent - TSQL JobStep%‘ THEN
 8 (SELECT ‘SQL AGENT JOB: ‘+name FROM msdb..sysjobs WHERE job_id=DBO.ConvertStringToBinary (LTRIM(RTRIM((SUBSTRING(es.program_name,CHARINDEX(‘(job‘,es.program_name,0)+4,35)))))
 9 )ELSE es.program_name END  AS program_name ,
10 DB_NAME(er.database_id) AS DatabaseName,
11 er.session_id,
12 wt.blocking_session_id,
13 wt.wait_duration_ms,
14 wt.wait_type,
15 wt.NoThread ,
16 er.command,
17 er.status,
18 er.wait_resource,
19 er.open_transaction_count,
20 er.cpu_time,
21 er.total_elapsed_time AS ElapsedTime_ms,
22 er.percent_complete ,
23 er.reads,er.writes,er.logical_reads,
24 wlgrp.name AS ResoursePool              ,
25 SUBSTRING (sqltxt.TEXT,(er.statement_start_offset/2) + 1,
26 ((CASE WHEN er.statement_end_offset = -1
27 THEN LEN(CONVERT(NVARCHAR(MAX), sqltxt.TEXT)) * 2
28 ELSE er.statement_end_offset
29 END - er.statement_start_offset)/2) + 1) AS [Individual Query],
30 sqltxt.TEXT AS [Batch Query]
31 FROM
32 SYS.DM_EXEC_REQUESTS  er INNER JOIN SYS.DM_EXEC_SESSIONS es ON es.session_id= er.session_id
33 INNER JOIN SYS.DM_RESOURCE_GOVERNOR_WORKLOAD_GROUPS wlgrp ON wlgrp.group_id=er.group_id
34 INNER JOIN  (SELECT  os.parent_node_id ,task_address FROM SYS.DM_OS_SCHEDULERS  OS
35 INNER JOIN SYS.DM_OS_WORKERS  OSW ON OS.scheduler_address=OSW.scheduler_address
36 WHERE os.status=‘VISIBLE ONLINE‘ GROUP BY os.parent_node_id ,task_address ) node ON node.task_address=er.task_address
37 LEFT JOIN
38 (SELECT session_id, SUM(wait_duration_ms) AS
39 wait_duration_ms,wait_type,blocking_session_id,COUNT(*) AS NoThread
40 FROM  SYS.DM_OS_WAITING_TASKS  GROUP BY session_id, wait_type,blocking_session_id) wt
41 ON wt.session_id=er.session_id
42 CROSS apply SYS.DM_EXEC_SQL_TEXT(er.sql_handle) AS sqltxt
43 WHERE sql_handle IS NOT NULL AND ISNULL(wt.wait_type ,‘‘) NOT IN
44 (‘WAITFOR‘,‘BROKER_RECEIVE_WAITFOR‘)
45 ORDER BY er.total_elapsed_time DESC
46
47 GO 

这里的输出列和第2步完全相同,我会分析total_elapsed_time占用时间较长的会话,酌情考虑是否终止这些会话,并分析下对应的执行SQL语句。大多数情况下(服务器一致运行稳定,突然卡住了),使用上述步骤就可以解决问题。下一篇文章我们会看下阻塞的会话,还有打开未活动事务的会话

时间: 2024-08-11 05:46:17

初涉SQL Server性能问题(2/4):列出等待资源的会话的相关文章

初涉SQL Server性能问题(4/4):列出最耗资源的会话

原文:初涉SQL Server性能问题(4/4):列出最耗资源的会话 在上3篇文章里,我们讨论了列出反映服务器当前状态的不同查询. 初涉SQL Server性能问题(1/4):服务器概况 初涉SQL Server性能问题(2/4):列出等待资源的会话 初涉SQL Server性能问题(3/4):列出阻塞的会话 这篇文章我们看下从计划缓存里列出执行状态. 1 /*********************************************************************

初涉SQL Server性能问题(3/4):列出阻塞的会话

原文:初涉SQL Server性能问题(3/4):列出阻塞的会话 在 初涉SQL Server性能问题(2/4)里,我们讨论了列出等待资源或正运行的会话脚本.这篇文章我们会看看如何列出包含具体信息的话阻塞会话清单. 1 /******************************************************************************************/ 2 CREATE FUNCTION [dbo].dba_GetStatementForSpid

初涉SQL Server性能问题(1/4):服务器概况

原文:初涉SQL Server性能问题(1/4):服务器概况 当你作为DBA时,很多人会向你抱怨:“这个程序数据加载和蜗牛一样,你看看是不是服务器出问题了?”造成这个问题的原因有很多.可能是程序应用服务器问题,网络问题,程序实现方式问题,数据库服务器负荷过重.不管是哪个问题,数据库总是第一个被抱怨的.我们DBA的职责就是找出问题所在,并解决它们. 问题解决第一步,诊断分析: 1 SELECT 2 parent_node_id AS Node_Id, 3 COUNT(*) AS [No.of CP

初涉SQL Server性能问题(1/4)

当你作为DBA时,很多人会向你抱怨:“这个程序数据加载和蜗牛一样,你看看是不是服务器出问题了?”造成这个问题的原因有很多.可能是程序应用服务器问题,网络问题,程序实现方式问题,数据库服务器负荷过重.不管是哪个问题,数据库总是第一个被抱怨的.我们DBA的职责就是找出问题所在,并解决它们. 问题解决第一步,诊断分析: 1 SELECT 2 parent_node_id AS Node_Id, 3 COUNT(*) AS [No.of CPU In the NUMA], 4 SUM(COUNT(*))

SQL Server 性能调优4 之书写高效的查询

限制查询的行和列来提高性能 这条规则非常简单,这里就不细说了. 使用搜索可参数化判断(sargable conditions)来提高性能 Sargable 由 Search ARGument Able 简写而来,字面意思是搜索可参数化?还是比较晦涩哎... 总之使用Sargable判断可以帮助查询优化器更有效地利用索引,并提高采用 index seek 的可能性,我们先把所有的操作符分一下组. Sargable操作符 = > >= < <= BETWEEN LIKE (通配符必须出

SQL SERVER性能分析--死锁检测数据库阻塞语句

工作中数据库经常出现内存,找了篇文章 参照CSDN,中国风(Roy)一篇死锁文章 阻塞:其中一个事务阻塞,其它事务等待对方释放它们的锁,同时会导致死锁问题. 整理人:中国风(Roy) 参照Roy_88的博客 http://blog.csdn.net/roy_88/archive/2008/07/21/2682044.aspx 日期:2008.07.20 ************************************************************************

Sql Server 性能优化之包含列

Sql Server 性能优化之包含列 导读:数据数优化查询一直是个比较热门的话题,小生在这方面也只能算是个入门生.今 天我们就讲下数据库包含列这个一项的作用及带来的优化效果 引用下MSDN里面的一段解释: 当查询中的所有列都作为键列或非键列包含在索引中时,带有包含性非键列的索引可以显 著提高查询性能. 这样可以实现性能提升,因为查询优化器可以在索引中找到所有列值:不 访问表或聚集索引数据,从而减少磁盘 I/O 操作 上面这一段什么意思呢? 意思就是说设置好包含列,能提高查询性能,减少IO输出.

识别SQL Server 性能杀手

性能优化的重点在于识别定位问题,预先了解主要的性能杀手,能够更快的定位到问题并将工作集中在可能的原因之上. SQL SERVER性能杀手主要集中在如下几类: 1.1   低质量的索引 低质量的索引通常是SQL SERVER最大的性能杀手,对于一个缺乏索引的查询,SQL SERVER 需要处理大量的读取和计算:这样导致磁盘.内存.CUP上有很大的开销,并且会显著的增加了查询执行时间. 1.2   不精确的统计信息 统计信息是谓词引用的列中的数据分布,其存储的方式为柱状图:柱状图是显示数据分布于不同

SQL Server 性能调优3 之索引(Index)的维护

SQL Server 性能调优3 之索引(Index)的维护 热度1 评论 16 作者:溪溪水草 前言 前一篇的文章介绍了通过建立索引来提高数据库的查询性能,这其实只是个开始.后续如果缺少适当的维护,你先前建立的索引甚至会成为拖累,成为数据库性能的下降的帮凶. 查找碎片 消除碎片可能是索引维护最常规的任务,微软官方给出的建议是当碎片等级为 5% - 30% 之间时采用 REORGANIZE 来“重整”索引,如果达到 30% 以上则使用 REBUILD 来“重建”索引.决定采用何种手段和操作时机可