46

実行するEXEC sp_who2 78と、次の結果が得られます。

spid 78 の sp_who2 の結果

ステータスが中断されている理由を確認するにはどうすればよいですか?

このプロセスはINSERT、コストのかかるクエリに基づいた重いものです。SELECT複数のテーブルからデータを取得し、約 3 ~ 400 万行を別のテーブルに書き込むビッグ。

ロック/ブロックはありません。

waittypeリンク先はですCXPACKET。下の写真でわかるように 9 つの 78 があるので、これは理解できます。

私が気になっていること、そして本当に知りたいことは、なぜSPID78 の背番号 1 が出場停止になったのかということです。

のステータス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 である可能性があり、WAITit はネットワーク上の通信である可能性があるか、ロックまたはラッチを待機している可能性があります。待機中のタスクが完了するとアクティブになります。たとえば、クエリが完全なテーブル tblStudents のデータを読み取る I/O 要求をポストした場合、このタスクは 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 に答える
0

次の方法で解決できます。

  1. クラスタ インデックスを修正します。
  2. テンポラル テーブルを使用して、すべてのテーブルの一部を取得し、それを操作します。

4億行のテーブルでも同じ問題があり、テンポラルテーブルを使用してその一部を取得し、インデックスの変更がオプションではなかったため、フィルターとインナーを使用します。

いくつかの例:

--
--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 に答える