Consultas para ver rápidamente lo que está haciendo tu SQL Server AHORA

Al solucionar problemas de rendimiento en una instancia de SQL Server, el primer paso es siempre entender qué está ocurriendo en este momento: qué consultas se están ejecutando, qué sesiones están bloqueando a otras y en qué esperas se está invirtiendo el tiempo. Estos tres scripts T-SQL ofrecen una imagen inmediata de la carga de trabajo actual mediante las Vistas de Administración Dinámica (DMVs).

1. Consultas Bloqueadas y Bloqueantes

Si esta consulta no devuelve filas, no hay consultas bloqueadas en este momento. Ejecútela varias veces para detectar cadenas de bloqueo de corta duración. Nota: esto muestra únicamente el bloqueo actual — la contención de bloqueos acumulada a corto plazo requiere un análisis de estadísticas de espera (véase la sección 2).

SELECT 'BLOCKING STATUS' AS Controllo,
    BlockedSPID     = LEFT(blocked.session_id, 5),
    BlockedQuery    = CONVERT(VARCHAR(50), blockedsql.text),
    BlockingSPID    = CONVERT(VARCHAR(50), blocking.session_id),
    BlockingQuery   = CONVERT(VARCHAR(50), blockingsql.text)
FROM sys.dm_exec_requests blocked
JOIN sys.dm_exec_requests blocking
    ON blocked.blocking_session_id = blocking.session_id
CROSS APPLY (SELECT * FROM sys.dm_exec_sql_text(blocked.sql_handle))  blockedsql
CROSS APPLY (SELECT * FROM sys.dm_exec_sql_text(blocking.sql_handle)) blockingsql;

2. Análisis de Eventos de Espera

SQL Server recopila continuamente estadísticas de espera en sys.dm_os_wait_stats desde el último reinicio de la instancia. Restablecer esta vista y recopilar datos durante un intervalo breve proporciona una imagen enfocada de en qué está invirtiendo tiempo la instancia — E/S, CPU, bloqueos, pestillos y más. Para una referencia completa de los tipos de eventos de espera, consulte la documentación de MSDN. El script siguiente está basado en la conocida metodología de análisis de esperas de Paul Randal.

DBCC SQLPERF ('sys.dm_os_wait_stats', CLEAR); -- Reset the DMV
GO

SELECT
    [owt].[session_id],
    [owt].[exec_context_id],
    [owt].[wait_duration_ms],
    [owt].[wait_type],
    [owt].[blocking_session_id],
    [owt].[resource_description],
    [es].[program_name],
    [est].[text],
    [est].[dbid],
    [eqp].[query_plan],
    [es].[cpu_time],
    [es].[memory_usage]
FROM sys.dm_os_waiting_tasks [owt]
INNER JOIN sys.dm_exec_sessions  [es]  ON [owt].[session_id] = [es].[session_id]
INNER JOIN sys.dm_exec_requests  [er]  ON [es].[session_id]  = [er].[session_id]
OUTER APPLY sys.dm_exec_sql_text   ([er].[sql_handle])   [est]
OUTER APPLY sys.dm_exec_query_plan ([er].[plan_handle])  [eqp]
WHERE [es].[is_user_process] = 1
ORDER BY [owt].[session_id], [owt].[exec_context_id];

3. Transacciones Abiertas con Texto de Consulta y Plan de Ejecución

sp_who2 y sys.dm_exec_requests muestran las sesiones actuales, pero no exponen fácilmente el texto completo de la consulta ni el plan de ejecución de cada transacción abierta. Este script — también de la colección SQLskills de Paul Randal — combina las DMVs de transacciones para recuperar exactamente eso, incluyendo el uso del log por transacción. Es especialmente útil para diagnosticar transacciones de larga duración que mantienen bloqueos o consumen espacio en el log de transacciones.

SELECT
    s_tst.[session_id],
    s_es.[login_name]                               AS [Login Name],
    DB_NAME(s_tdt.database_id)                      AS [Database],
    s_tdt.[database_transaction_begin_time]         AS [Begin Time],
    s_tdt.[database_transaction_log_record_count]   AS [Log Records],
    s_tdt.[database_transaction_log_bytes_used]     AS [Log Bytes],
    s_tdt.[database_transaction_log_bytes_reserved] AS [Log Reserved],
    s_est.[text]                                    AS [Last T-SQL Text],
    s_eqp.[query_plan]                              AS [Last Plan]
FROM sys.dm_tran_database_transactions s_tdt
JOIN  sys.dm_tran_session_transactions s_tst ON s_tst.[transaction_id] = s_tdt.[transaction_id]
JOIN  sys.dm_exec_sessions             s_es  ON s_es.[session_id]      = s_tst.[session_id]
JOIN  sys.dm_exec_connections          s_ec  ON s_ec.[session_id]      = s_tst.[session_id]
LEFT JOIN sys.dm_exec_requests         s_er  ON s_er.[session_id]      = s_tst.[session_id]
CROSS APPLY sys.dm_exec_sql_text  (s_ec.[most_recent_sql_handle]) AS s_est
OUTER APPLY sys.dm_exec_query_plan(s_er.[plan_handle])            AS s_eqp
ORDER BY [Begin Time] ASC;