DBA工具——DMV——如何知道TSQL語句已執行了多久

發糞塗牆發表於2012-05-29

DBA通常想知道正在執行的語句已經執行了多久了?可以使用Sqlserver profiler來捕獲語句的開始時間,和現有時間比較,但是在生產環境下通常會對效能有負面影響,所以通常不建議在非必要的前提下在生產環境使用SQL Server Profiler。

此時,可以使用DMV來查詢:

sys.dm_exec_requests中有一個重要欄位:start_time,表示request的開始時間,一個批處理就是一個request,一個request對應一個task,如果批處理是併發,則對應多個tasks。下面指令碼不考慮併發情況。在DMV中的sys.dm_os_workers裡面有一個欄位task_bound_ms_ticks表示執行緒(worker)拿到task的時間(單位是tick)。

由於sys.dm_exec_requests沒有包含語句文字,所以需要藉助sys.dm_exec_sql_text轉換sql_handle而得到。然後從sys.dm_exec_query_plan得到執行計劃。還輸出正在執行的哪一句具體的stmt。這對於一個批處理包含多條語句時特別有用:


DECLARE @ms_per_tick DECIMAL(10, 6)
 --millisecond per tick
SELECT  @ms_per_tick = 1.0 * DATEDIFF(millisecond, sqlserver_start_time,
                                      GETDATE()) / ( ms_ticks
                                                     - sqlserver_start_time_ms_ticks )
FROM    sys.[dm_os_sys_info] ;

--select @ms_per_tick

SELECT  req.session_id ,
        req.start_time request_start_time ,
        ( ( SELECT  ms_ticks
            FROM    sys.dm_os_sys_info
          ) - workers.task_bound_ms_ticks ) * @ms_per_tick 'ms_since_task_bound' ,
        DATEDIFF(ms, req.start_time, GETDATE()) 'ms_since_request_start' ,
        tasks.task_state ,
        workers.state worker_state ,
        req.status request_state ,
        st.text ,
        SUBSTRING(st.text, ( req.statement_start_offset / 2 ) + 1,
                  ( ( CASE req.statement_end_offset
                        WHEN -1 THEN DATALENGTH(st.text)
                        ELSE req.statement_end_offset
                      END - req.statement_start_offset ) / 2 ) + 1) AS stmt ,
        qp.query_plan ,
        req.*
FROM    sys.dm_exec_requests req
        LEFT JOIN sys.dm_os_tasks tasks ON tasks.task_address = req.task_address
        LEFT JOIN sys.dm_os_workers workers ON tasks.task_address = workers.task_address
        CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) st
        CROSS APPLY sys.dm_exec_query_plan(req.plan_handle) qp
WHERE   ( req.session_id > 50
          OR req.session_id IS NULL
        )

go

上面的@ms_per_tick用來計算一個tick相當與多少ms(毫秒),一般一個tick基本就是一毫秒。輸出如下:


相關文章