46

我运行EXEC sp_who2 78并得到以下结果

spid 78 的 sp_who2 结果

我怎样才能找到它的状态为什么被暂停?

这个过程是一个沉重INSERT的基于昂贵的查询。一个SELECT从多个表中获取数据并将大约 3-4 百万行写入不同表的大数据。

没有锁/块。

waittype链接到的是CXPACKET。我可以理解,因为您可以在下图中看到 9 个 78。

让我担心并且我真正想知道的是,为什么SPID78 的 1 号被停赛。

我知道当 a 的状态SPID被挂起时,这意味着该进程正在等待资源,并且在获得资源时它将恢复。

我怎样才能找到有关此的更多详细信息?什么资源?为什么不可用?

我使用了很多下面的代码及其变体,但是我还能做些什么来找出SPID暂停的原因吗?

select * 
from sys.dm_exec_requests r
join sys.dm_os_tasks t on r.session_id = t.session_id
where r.session_id = 78

我已经使用了 sp_whoisactive。我为这个特定的 spid78 得到的结果如下:(分成 3 张图片以适应屏幕)

在此处输入图像描述

4

3 回答 3

53

SUSPENDED:表示请求当前不活跃,因为它正在等待资源。资源可以是一个读取页面的I/O,一个WAIT可以是网络上的通信,也可以是等待锁或闩锁。一旦它等待的任务完成,它将变为活动状态。例如,如果查询已发布 I/O 请求以读取完整表 tblStudents 的数据,则此任务将暂停,直到 I/O 完成。一旦 I/O 完成(表 tblStudents 的数据在内存中可用),查询将移动到 RUNNABLE 队列。

所以如果它正在等待,请检查 wait_type 列以了解它在等待什么,并根据 wait_time 进行故障排除。

我开发了以下程序来帮助我解决这个问题,它包括 WAIT_TYPE。

use master
go

CREATE PROCEDURE [dbo].[sp_radhe] 

AS
BEGIN

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

SELECT es.session_id AS session_id
,COALESCE(es.original_login_name, '') AS login_name
,COALESCE(es.host_name,'') AS hostname
,COALESCE(es.last_request_end_time,es.last_request_start_time) AS last_batch
,es.status
,COALESCE(er.blocking_session_id,0) AS blocked_by
,COALESCE(er.wait_type,'MISCELLANEOUS') AS waittype
,COALESCE(er.wait_time,0) AS waittime
,COALESCE(er.last_wait_type,'MISCELLANEOUS') AS lastwaittype
,COALESCE(er.wait_resource,'') AS waitresource
,coalesce(db_name(er.database_id),'No Info') as dbid
,COALESCE(er.command,'AWAITING COMMAND') AS cmd
,sql_text=st.text
,transaction_isolation =
    CASE es.transaction_isolation_level
    WHEN 0 THEN 'Unspecified'
    WHEN 1 THEN 'Read Uncommitted'
    WHEN 2 THEN 'Read Committed'
    WHEN 3 THEN 'Repeatable'
    WHEN 4 THEN 'Serializable'
    WHEN 5 THEN 'Snapshot'
END
,COALESCE(es.cpu_time,0) 
    + COALESCE(er.cpu_time,0) AS cpu
,COALESCE(es.reads,0) 
    + COALESCE(es.writes,0) 
    + COALESCE(er.reads,0) 
    + COALESCE(er.writes,0) AS physical_io
,COALESCE(er.open_transaction_count,-1) AS open_tran
,COALESCE(es.program_name,'') AS program_name
,es.login_time
FROM sys.dm_exec_sessions es
    LEFT OUTER JOIN sys.dm_exec_connections ec ON es.session_id = ec.session_id
    LEFT OUTER JOIN sys.dm_exec_requests er ON es.session_id = er.session_id
    LEFT OUTER JOIN sys.server_principals sp ON es.security_id = sp.sid
    LEFT OUTER JOIN sys.dm_os_tasks ota ON es.session_id = ota.session_id
    LEFT OUTER JOIN sys.dm_os_threads oth ON ota.worker_address = oth.worker_address
    CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS st
where es.is_user_process = 1 
  and es.session_id <> @@spid
ORDER BY es.session_id

end 

下面的这个查询还可以显示基本信息,以便在 spid 暂停时提供帮助,方法是显示 spid 正在等待哪个资源。

SELECT  wt.session_id, 
    ot.task_state, 
    wt.wait_type, 
    wt.wait_duration_ms, 
    wt.blocking_session_id, 
    wt.resource_description, 
    es.[host_name], 
    es.[program_name] 
FROM  sys.dm_os_waiting_tasks  wt  
INNER  JOIN sys.dm_os_tasks ot ON ot.task_address = wt.waiting_task_address 
INNER JOIN sys.dm_exec_sessions es ON es.session_id = wt.session_id 
WHERE es.is_user_process =  1 

请以下图为例:

在此处输入图像描述

于 2014-09-27T20:16:55.477 回答
14

我使用 sp_whoIsActive 来查看此类信息,因为它是一个现成的免费工具,可为您提供解决慢查询问题的良好信息:

如何使用 sp_WhoIsActive 查找慢速 SQL Server 查询

有了这个,您可以获得查询文本、它正在使用的计划、查询正在等待的资源、阻塞它的原因、它取出的锁等等。

比尝试自己动手要容易得多。

于 2014-02-26T10:43:42.407 回答
0

您可以通过以下方式解决它:

  1. 修复集群索引。
  2. 使用临时表获取所有表的一部分并使用它。

我对一个有 400,000,000 行的表有同样的问题,并使用一个临时表来获取它的一部分,然后我使用我的过滤器和内部,因为更改索引不是一个选项。

一些例子:

--
--this is need be cause DECLARE @TEMPORAL are not well for a lot of data.
CREATE TABLE #TEMPORAL
(
    ID BIGINT,
    ID2 BIGINT,
    DATA1 DECIMAL,
    DATA2 DECIMAL
);

WITH TABLE1 AS
(
    SELECT
        L.ID,
        L.ID2,
        L.DATA
    FROM LARGEDATA L
    WHERE L.ID = 1
), WITH TABLE2 AS
(
    SELECT
        L.ID,
        L.ID2,
        L.DATA
    FROM LARGEDATA L
    WHERE L.ID = 2
) INSERT INTO #TEMPORAL SELECT
    T1.ID,
    T2.ID,
    T1.DATA,
    T2.DATA
FROM TABLE1 T1
    INNER JOIN TABLE2 T2
        ON T2.ID2 = T2.ID2;
--
--this take a lot of resources proces and time and be come a status suspend, this why i need a temporal table.
SELECT
    *
FROM #TEMPORAL T
WHERE T.DATA1 < T.DATA2
--
--IMPORTANT DROP THE TABLE.
DROP TABLE #TEMPORAL
于 2017-03-29T22:43:02.477 回答