Pregunta

Corro EXEC sp_who2 78 y me sale lo siguiente resultados:

results of sp_who2 for spid 78

¿Cómo puedo saber por qué su estado está suspendido?

Este proceso es pesado INSERT basado en una consulta costosa.Un gran SELECT que obtiene datos de varias tablas y escribe entre 3 y 4 millones de filas en una tabla diferente.

No hay cerraduras/bloqueos.

El waittype está vinculado a es CXPACKET.Lo cual puedo entender porque hay 9 78 como puedes ver en la imagen de abajo.

Lo que me preocupa y lo que realmente me gustaría saber es por qué el número 1 del SPID 78 está suspendido.

Entiendo que cuando el estado de un SPID está suspendido significa que el proceso está esperando un recurso y se reanudará cuando obtenga su recurso.

¿Cómo puedo encontrar más detalles sobre esto?¿Qué recurso?¿por qué no está disponible?

Utilizo mucho el código siguiente y sus variaciones, pero ¿hay algo más que pueda hacer para descubrir por qué SPID ¿está suspendido?

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

ya usé sp_whoisactive.El resultado que obtengo para este spid78 en particular es el siguiente:(dividido en 3 fotos para que quepan en la pantalla)

enter image description here

¿Fue útil?

Solución

suspendido: Significa que la solicitud actualmente no está activa porque está esperando un recurso. El recurso puede ser una E / S para leer una página, un camarero puede ser comunicación en la red, o está esperando el bloqueo o un pestillo. Se volverá activo una vez que se complete la tarea que esté esperando. Por ejemplo, si la consulta ha publicado una solicitud de E / S para leer los datos de una tabla completa TBLStudes, entonces esta tarea se suspenderá hasta que la E / S esté completa. Una vez completado la E / S (los datos para TABLESTUSIONES DE TABLER están disponibles en la memoria), la consulta se moverá a la cola de funcionamiento.

Entonces, si está esperando, marque la columna WAIT_TYPE para comprender lo que está esperando y solucionar problemas en función de la espera.

He desarrollado el siguiente procedimiento que me ayuda con esto, incluye el 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 a continuación también puede mostrar información básica para ayudar cuando se suspende el SPID, mostrando qué recurso está esperando el 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 

Por favor, consulte la imagen a continuación como ejemplo:

ingrese la descripción de la imagen aquí

Otros consejos

Utilizo SP_Whoisactive Para ver este tipo de información, ya que es una herramienta gratuita lista para que le brinda una buena información para la solución de problemas de consultas lentas:

Cómo usar SP_Whoisactive para encontrar consultas lentas de SQL Server

Con esto, puede obtener el texto de la consulta, el plan que está usando, el recurso está esperando la consulta, lo que lo está bloqueando, lo que los bloquea está sacando y mucho más.

mucho más fácil que intentar rodar el tuyo.

Puede resolverlo con las formas:

  1. arreglar el índice de clúster.
  2. Use las tablas temporales para obtener una parte de la tabla y trabajar con él.
  3. Tengo el mismo problema con una tabla con 400,000,000 filas, y use las tablas temporales para obtener una parte de ella y luego utilizo mis filtros e internos porque cambie el índice no fue una opción.

    Algunos ejemplo:

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top