Como saber qual o status de um spid está suspenso?Quais os recursos que o spid está à espera?
-
21-12-2019 - |
Pergunta
Eu corro EXEC sp_who2 78
e eu recebo o seguinte resultados:
Como posso descobrir por que seu status é suspensa?
Este processo é pesado INSERT
com base em um cara de consulta.Um grande SELECT
que obtém dados a partir de várias tabelas e escrever algumas 3-4 milhões de linhas em uma tabela diferente.
Não há bloqueios/ blocos.
O waittype
ele está ligado é CXPACKET
.o que eu posso entender porque há 9 78 como você pode ver na imagem abaixo.
O que me preocupa e o que eu realmente gostaria de saber é por que o número 1 do SPID
78 é suspenso.
Eu entendo que quando o status de um SPID
é suspensa significa que o processo está aguardando um recurso e ele vai continuar quando ele recebe o recurso.
Como posso encontrar mais detalhes sobre isso?quais recursos?por que ele não está disponível?
Eu uso muito o código abaixo e variações dela, mas há mais alguma coisa que eu possa fazer para descobrir por que o SPID
é suspensa?
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
Eu já usei sp_whoisactive.O resultado eu recebo para este particular spid78 é como a seguir:(dividida em 3 fotos para o ajuste da tela)
Solução
SUSPENSÃO:Isso significa que o pedido não está ativo porque ele está aguardando um recurso.O recurso pode ser uma e/S para ler uma página, Um WAITit pode ser a comunicação na rede, ou está à espera de bloqueio ou de uma fechadura.Ele ficará ativo uma vez que a tarefa está esperando é concluída.Por exemplo, se a consulta a postou um pedido de e/S para ler dados de uma tabela completa tblStudents, em seguida, esta tarefa será suspenso até que a e/S é concluída.Uma vez de e/S é concluída (Dados para a tabela tblStudents disponível na memória), a consulta irá mover-se em fila EXECUTÁVEL.
Por isso, se está à espera, verifique o wait_type coluna para entender o que ele está esperando por e solucionar problemas com base na wait_time.
Eu desenvolvi o seguinte procedimento que me ajuda com isso, ele inclui o 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
Esta consulta abaixo também podem mostrar informações básicas para ajudá-los quando o spid está suspenso, mostrando qual o recurso que o spid está aguardando.
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
Por favor, veja a imagem abaixo como exemplo:
Outras dicas
Eu uso sp_whoIsActive olhar para este tipo de informação, pois ela está pronta ferramenta gratuita que lhe dá boas informações para solução de consultas lentas:
Como Usar sp_WhoIsActive para Encontrar Lento Consultas do SQL Server
Com isso, você pode obter o texto da consulta, o plano está usando, o recurso a consulta está esperando, o que está bloqueando ele, os bloqueios que ele está tomando e um lote inteiro de mais.
Muito mais fácil do que tentar reverter seu próprio.
Você pode resolvê-lo com a maneiras:
- Correção o índice de cluster.
- Use temporal tabelas para obter uma parte do todo, mesa e trabalhar com ele.
Eu tenho o mesmo problema com uma tabela com um 400,000,000 linhas, e usar um temporal tabelas para obter uma parte do mesmo e, em seguida, eu uso o meu filtros e ampolas porque alterar o índice não foi uma opção.
Alguns exemplos:
--
--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