Domanda Come scoprire perché lo stato di uno spid è sospeso? Quali risorse lo spid sta aspettando?


io corro EXEC sp_who2 78 e ottengo i seguenti risultati:

results of sp_who2 for spid 78

Come posso scoprire perché il suo stato è sospeso?

Questo processo è pesante INSERT basato su una query costosa. Un grande SELECT che ottiene i dati da più tabelle e scrive circa 3-4 milioni di righe su una tabella diversa.

Non ci sono serrature / blocchi.

Il waittype è collegato a è CXPACKET. che posso capire perché ci sono 9 78 come potete vedere nella foto qui sotto.

Ciò che mi preoccupa e quello che vorrei davvero sapere è perché il numero 1 del SPID 78 è sospeso.

Capisco che quando lo stato di a SPID è sospeso significa che il processo è in attesa su una risorsa e riprenderà quando avrà la sua risorsa.

Come posso trovare maggiori dettagli a riguardo? quale risorsa? perché non è disponibile?

Io uso molto il codice qui sotto, e le variazioni da esso, ma c'è qualcos'altro che posso fare per scoprire perché il SPID è sospeso?

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

L'ho già usato sp_whoisactive. Il risultato che ottengo per questo particolare spid78 è il seguente: (suddiviso in 3 foto per adattarsi allo schermo)

enter image description here


27
2018-02-26 10:34


origine


risposte:


SOSPESO: Significa che la richiesta al momento non è attiva perché è in attesa su una risorsa. La risorsa può essere un I / O per la lettura di una pagina, un WAITit può essere una comunicazione sulla rete o è in attesa di un blocco o di un latch. Diventerà attivo una volta completata l'attività che sta aspettando. Ad esempio, se la query ha pubblicato una richiesta I / O per leggere i dati di una tabella completa tblStudents, questa attività verrà sospesa fino al completamento dell'I / O. Una volta completato l'I / O (i dati per tblStudents della tabella sono disponibili in memoria), la query verrà spostata nella coda RUNNABLE.

Quindi, se è in attesa, controlla la colonna wait_type per capire cosa sta aspettando e risolvi i problemi in base al wait_time.

Ho sviluppato la seguente procedura che mi aiuta con questo, include 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 

Questa query sotto può anche mostrare le informazioni di base per assistere quando lo spid è sospeso, mostrando quale risorsa lo spid sta aspettando.

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 

Si prega di vedere l'immagine qui sotto come un esempio:

enter image description here


25
2017-09-27 20:16



Io uso sp_whoIsActive per esaminare questo tipo di informazioni in quanto è uno strumento gratuito pronto che ti fornisce buone informazioni per la risoluzione di query lente:

Come utilizzare sp_WhoIsActive per trovare query SQL Server lente

Con questo, è possibile ottenere il testo della query, il piano che sta utilizzando, la risorsa su cui la query è in attesa, cosa lo blocca, quali blocchi sta eliminando e molto altro.

Molto più facile che provare a tirare il tuo.


12
2018-02-26 10:43



Puoi risolverlo con modi:

  1. Correggi l'indice del cluster.
  2. Utilizza le tabelle temporali per ottenere una parte di tutte le tabelle e lavorare con essa.

Ho lo stesso problema con una tabella con 400.000.000 di righe, e uso una tabella temporale per ottenerne una parte e quindi uso i miei filtri e gli interi perché cambiare l'indice non era un'opzione.

Qualche esempio:

--
--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

0
2018-03-29 22:43