Como medir el progreso del rollback de una transaccion

Muchas veces nos encontramos con casos de consultas (queries) que estan modificando datos por largos periodos de tiempo y honestamente lo ultimo que quiero hacer en esos momentos es terminar el proceso; si se da el caso que el Log de la base de datos se lleno es preferible crear un log temporal en otra unidad y esperar a que la transacción termine por si misma. Pero si se da el caso que no podemos esperar y hay que terminar o matar la transacción ya tenemos a nuestro jefe o cliente presionando por ello, siempre es util saber cual es el % del progreso del rollback, para ello utilizamos el mismo comando KILL <SPID> WITH STATUSONLY, este comando nos dara un estimado del porcentaje.

Para reproducir, generar un ciclo de inserción en cualquier tabla, en este ejemplo insertamos texto infinitamente:


CREATE TABLE tprueba
(
id    INT NOT NULL IDENTITY(1, 1),
texto VARCHAR(15),
CONSTRAINT pk_tprueba PRIMARY KEY (id)
)

WHILE EXISTS(SELECT 1
FROM   sys.tables
WHERE  name = 'Tprueba')
BEGIN
INSERT INTO tprueba
VALUES      (' Es Una Prueba ')
END

Una vez que tengamos el código en ejecución procedamos a matar o terminar la transacción que recien iniciamos


KILL <SPID>

Una vez en estado rollback ejecutamos la misma instrucción de KILL con el parámetro [statusonly]

KILL <spid> WITH statusonly


Monitorear el uso de Procedimientos Almacenados

Hace un tiempo habia encontrado estas consultas para monitorear el uso de procedimientos almacenados en SQL 2005 y posterior. Los comparto porque siempre es util conocer que tanto y que tan frecuentemente se ejecutan nuestros procedimientos almacenados.

1. [Conteo Total de Ejecuciones]

SELECT 
    Db_name(st.dbid) [Base de Datos],
    Object_schema_name(st.objectid, dbid) [Schema],
    Object_name(st.objectid, dbid)        [USP],
    Max(cp.usecounts)                     [Total Ejecuciones]
FROM   
    sys.dm_exec_cached_plans cp
    CROSS apply sys.Dm_exec_sql_text(cp.plan_handle) st
WHERE  
    Db_name(st.dbid) IS NOT NULL
    AND cp.objtype = 'proc'
GROUP  BY 
    cp.plan_handle,
    Db_name(st.dbid),
    Object_schema_name(objectid, st.dbid),
    Object_name(objectid, st.dbid)
ORDER  BY 
        Max(cp.usecounts)

2. [Procedimiento que Consume mas CPU]

 SELECT 
    Db_name(st.dbid)
    [Base de Datos, Object_schema_name(st.objectid, dbid) [Schema],
    Object_name(st.objectid, dbid) [USP],
    Max(cp.usecounts) [Total Ejecuciones],
    Sum(qs.total_worker_time) [Consumo Total CPU],
    Sum(qs.total_worker_time) / ( Max(cp.usecounts) * 1.0 )    [Consumo Promedio CPU]
FROM   
    sys.dm_exec_cached_plans cp
    INNER JOIN sys.dm_exec_query_stats qs
        ON cp.plan_handle = qs.plan_handle
    CROSS apply sys.Dm_exec_sql_text(cp.plan_handle) st
WHERE  
    Db_name(st.dbid) IS NOT NULL
    AND cp.objtype = 'proc'
GROUP  BY 
    Db_name(st.dbid),
    Object_schema_name(objectid, st.dbid),
    Object_name(objectid, st.dbid)
ORDER  BY 
    Sum(qs.total_worker_time) DESC   

3. [Procedimientos con mayor tiempo de ejecucion]

SELECT 
    Db_name(st.dbid) [Base de Datos, 
    Object_schema_name(objectid, st.dbid) [Schema],
    Object_name(objectid, st.dbid) [USP],
    Max(cp.usecounts) [Total Ejecuciones],
    Sum(qs.total_elapsed_time) [Tiempo Total Ejecuciones],
    Sum(qs.total_elapsed_time) / Max(cp.usecounts) [Tiempo Promedio Ejecuciones]
FROM   
    sys.dm_exec_query_stats qs
    CROSS apply sys.Dm_exec_sql_text(qs.plan_handle) st
    INNER JOIN sys.dm_exec_cached_plans cp
        ON qs.plan_handle = cp.plan_handle
WHERE  
    Db_name(st.dbid) IS NOT NULL
    AND cp.objtype = 'proc'
GROUP  BY 
    Db_name(st.dbid),
    Object_schema_name(objectid,st.dbid),
    Object_name(objectid, st.dbid)
ORDER  BY 
    Sum(qs.total_elapsed_time) DESC  

Fuente SQL Journal