Frage

Ich laufe EXEC sp_who2 78 und ich bekomme folgendes Suchergebnisse:

results of sp_who2 for spid 78

Wie kann ich herausfinden, warum sein Status ausgesetzt ist?

Dieser Prozess ist ein schwerer INSERT basierend auf einer teuren Abfrage.Groß SELECT das ruft Daten aus mehreren Tabellen ab und schreibt etwa 3-4 Millionen Zeilen in eine andere Tabelle.

Es gibt keine Schlösser / Blöcke.

Der waittype es ist mit dem is verbunden CXPACKET.was ich verstehen kann, weil es 9 78er gibt, wie Sie auf dem Bild unten sehen können.

Was mich beschäftigt und was ich wirklich gerne wissen würde, ist, warum die Nummer 1 der SPID 78 ist suspendiert.

Ich verstehe das, wenn der Status eines SPID ist angehalten, bedeutet dies, dass der Prozess auf eine Ressource wartet und fortgesetzt wird, wenn er seine Ressource erhält.

Wie kann ich weitere Details dazu finden?welche Ressource?warum ist es nicht verfügbar?

Ich benutze viel den folgenden Code und Variationen davon, aber kann ich noch etwas tun, um herauszufinden, warum der SPID ist suspendiert?

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

Ich habe schon benutzt sp_whoisaktiv.Das Ergebnis, das ich für diesen speziellen Spid78 erhalte, ist wie folgt:(in 3 Bilder unterteilt, um auf den Bildschirm zu passen)

enter image description here

War es hilfreich?

Lösung

AUSGESETZT:Dies bedeutet, dass die Anforderung derzeit nicht aktiv ist, da sie auf eine Ressource wartet.Die Ressource kann eine E / A zum Lesen einer Seite sein, eine Wartezeit kann Kommunikation im Netzwerk sein oder sie wartet auf eine Sperre oder eine Verriegelung.Es wird aktiv, sobald die Aufgabe, auf die es wartet, abgeschlossen ist.Wenn die Abfrage beispielsweise eine E / A-Anforderung zum Lesen von Daten einer vollständigen Tabelle tblStudents gesendet hat, wird diese Aufgabe ausgesetzt, bis die E / A abgeschlossen ist.Sobald die E / A abgeschlossen ist (Daten für die Tabelle tblStudents sind im Speicher verfügbar), wird die Abfrage in die AUSFÜHRBARE Warteschlange verschoben.

Wenn es also wartet, überprüfen Sie die Spalte wait_type, um zu verstehen, worauf es wartet, und beheben Sie Fehler basierend auf der Wartezeit.

Ich habe das folgende Verfahren entwickelt, das mir dabei hilft, es enthält den 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 

Diese Abfrage unten kann auch grundlegende Informationen anzeigen, die beim Anhalten der SPID hilfreich sind, indem angezeigt wird, auf welche Ressource die SPID wartet.

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 

Bitte sehen Sie sich das Bild unten als Beispiel an:

enter image description here

Andere Tipps

Ich verwende sp_whoIsActive, um diese Art von Informationen anzuzeigen, da es sich um ein fertiges kostenloses Tool handelt, das Ihnen gute Informationen zur Fehlerbehebung bei langsamen Abfragen liefert:

Verwendung von sp_WhoIsActive zum Auffinden langsamer SQL Server-Abfragen

Damit können Sie den Abfragetext, den verwendeten Plan, die Ressource, auf die die Abfrage wartet, was sie blockiert, welche Sperren sie entfernt und vieles mehr abrufen.

Viel einfacher als zu versuchen, deine eigenen zu rollen.

Sie können es auf verschiedene Arten lösen:

  1. Korrigieren Sie den Clusterindex.
  2. Verwenden Sie temporäre Tabellen, um einen Teil der all-Tabelle abzurufen und damit zu arbeiten.

Ich habe das gleiche Problem mit einer Tabelle mit 400.000.000 Zeilen und verwende eine temporale Tabelle, um einen Teil davon zu erhalten, und dann verwende ich meine Filter und Inners, da das Ändern des Index keine Option war.

Ein Beispiel:

--
--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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top