Je lance EXEC sp_who2 78
et j'obtiens les résultats suivants:
Comment trouver pourquoi son statut est suspendu?
Ce processus est une INSERT
lourde basée sur une requête coûteuse. Une grosse SELECT
qui récupère les données de plusieurs tables et écrit quelques 3-4 millions de lignes dans une autre table.
Il n'y a pas de serrures/blocs.
La waittype
à laquelle elle est liée 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 me préoccupe et ce que j'aimerais vraiment savoir, c'est pourquoi le numéro 1 de la SPID
78 est suspendu.
Je comprends que lorsque le statut de la variable SPID
est suspendu, cela signifie que le processus attend une ressource et qu’il reprendra dès qu’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 savoir pourquoi la variable 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 obtenu pour ce spid78 est le suivant: (divisé en 3 images pour correspondre à l'écran)
SUSPENDED: Cela signifie que la demande n'est pas active actuellement car elle attend une ressource. La ressource peut être une E/S pour lire une page, une WAITit peut être une communication sur le réseau, ou elle attend un verrou ou un verrou. Il deviendra actif une fois la tâche attendue terminée. Par exemple, si la requête a envoyé 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 en mémoire), la requête est transférée dans la file d'attente RUNNABLE.
Par conséquent, s'il attend, consultez la colonne wait_type pour comprendre ce qu'il attend et résolvez-le en fonction du wait_time.
J'ai développé la procédure suivante qui m'aide avec ceci, 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 attendue par le 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
S'il vous plaît voir l'image ci-dessous à titre d'exemple:
J'utilise sp_whoIsActive pour examiner ce type d'informations car il s'agit d'un outil gratuit prêt à l'emploi qui vous fournit de bonnes informations pour le dépannage des 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 utilisé, la ressource attendue par la requête, ce qui la bloque, ce qui la verrouille et bien plus encore.
Beaucoup plus facile que d'essayer de rouler le vôtre.
Vous pouvez le résoudre avec les moyens suivants:
J'ai le même problème avec une table avec 400 000 000 lignes et j'utilise une table temporelle pour en obtenir une partie, puis j'utilise mes filtres et mon inner, car changer l'index n'était pas une option.
Quelques exemples:
--
--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