Question

je cours EXEC sp_who2 78 et j'obtiens ce qui suit résultats:

results of sp_who2 for spid 78

Comment puis-je savoir pourquoi son statut est suspendu ?

Ce processus est un lourd INSERT basé sur une requête coûteuse.Un gros SELECT qui récupère les données de plusieurs tables et écrit environ 3 à 4 millions de lignes dans une table différente.

Il n'y a pas de verrous/blocs.

Le waittype il est lié à est CXPACKET.ce que je peux comprendre car il y a 9 78 comme vous pouvez le voir sur la photo ci-dessous.

Ce qui m'inquiète et ce que j'aimerais vraiment savoir, c'est pourquoi le numéro 1 du SPID 78 est suspendu.

Je comprends que lorsque le statut d'un SPID est suspendu, cela signifie que le processus attend une ressource et qu'il reprendra lorsqu'il obtiendra sa ressource.

Comment puis-je trouver plus de détails à ce sujet ?quelle ressource ?pourquoi n'est-il pas disponible ?

J'utilise beaucoup le code ci-dessous et ses variantes, mais puis-je faire autre chose pour découvrir pourquoi le SPID est suspendue?

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

j'ai déjà utilisé sp_whoisactive.Le résultat que j'obtiens pour ce spid78 particulier est le suivant :(divisé en 3 photos pour s'adapter à l'écran)

enter image description here

Était-ce utile?

La solution

SUSPENDU:Cela signifie que la requête n'est actuellement pas active car elle attend une ressource.La ressource peut être une E/S pour lire une page, une WAIT, une communication sur le réseau, ou elle attend un verrou ou un loquet.Il deviendra actif une fois la tâche qu’il attend terminée.Par exemple, si la requête a publié une demande d'E/S pour lire les données d'une table complète tblStudents, cette tâche sera suspendue jusqu'à ce que l'E/S soit terminée.Une fois les E/S terminées (les données de la table tblStudents sont disponibles dans la mémoire), la requête sera déplacée vers la file d'attente RUNNABLE.

Donc, s'il attend, vérifiez la colonne wait_type pour comprendre ce qu'il attend et dépannez en fonction du wait_time.

J'ai développé la procédure suivante qui m'aide, elle inclut le 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 

Cette requête ci-dessous peut également afficher des informations de base pour vous aider lorsque le spid est suspendu, en indiquant la ressource que le spid attend.

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 

Veuillez voir l'image ci-dessous à titre d'exemple :

enter image description here

Autres conseils

J'utilise sp_whoIsActive pour examiner ce type d'informations car il s'agit d'un outil gratuit prêt à l'emploi qui vous donne de bonnes informations pour dépanner les requêtes lentes :

Comment utiliser sp_WhoIsActive pour rechercher des requêtes SQL Server lentes

Avec cela, vous pouvez obtenir le texte de la requête, le plan qu'elle utilise, la ressource sur laquelle la requête attend, ce qui la bloque, quels verrous elle supprime et bien plus encore.

Beaucoup plus facile que d'essayer de rouler le vôtre.

Vous pouvez le résoudre de plusieurs manières :

  1. Corrigez l'index du cluster.
  2. Utilisez des tables temporelles pour obtenir une partie de la table all et travailler avec elle.

J'ai le même problème avec une table avec 400 000 000 de lignes, et j'utilise des tables temporelles pour en obtenir une partie, puis j'utilise mes filtres et mes internes car changer l'index n'était pas une option.

Quelques exemple :

--
--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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top