sys.dm_exec_requests - start_time

Ran*_*der 7 sql-server dmv

我有以下查询,它告诉我我负责的数据库中查询的状态(尽管我不是 DBA)。

SELECT 
     T3.FullStatement as FullSQLStatement
    ,T3.ExecutingStatement
    ,req.session_id as SessionId
    ,T2.login_name as LoginName
    ,command as SQLCommand
    ,start_time as StartTime
    ,DateDiff(MINUTE,start_time,GetDate()) as ElapsedTimeMinutes
    ,req.status as QueryStatus
    ,req.wait_type as WaitType
    ,req.wait_time as WaitTimeMs
    ,blocking_session_id as BlockingSessionId
    ,req.row_count as [RowCount]
    ,req.cpu_time as CpuTimeMs
    ,req.total_elapsed_time as TotalElapsedTimeMs
    ,SubString(sqltext.TEXT,req.statement_start_offset,req.statement_end_offset-req.statement_start_offset)
FROM sys.dm_exec_requests req
    Inner Join sys.dm_exec_sessions T2 ON T2.session_id = req.session_id
    Cross Apply dbo.GetExecutingSQLStatement (req.session_id) T3
    Cross Apply sys.dm_exec_sql_text(sql_handle) AS sqltext
where req.database_id = 5
Order By 6 Desc
Run Code Online (Sandbox Code Playgroud)

它生成的输出部分如下所示:

在此处输入图片说明 尽管它在我包含的示例中没有很好地显示,但 start_time 是完整语句的开始时间,而不是语句的执行部分。有什么地方可以获取执行部分的开始时间以及完整语句的开始时间。这对我很重要,因为很明显,一个完整的语句可能有许多单独的查询。

Sol*_*zky 8

目前这似乎不是一个可能的价值,这是不幸的,因为这似乎是一个方便的价值。

好的,我确实找到了(大部分)。sys.dm_exec_query_stats DMV 中有一个last_execution_time字段,尽管该 DMV 带有以下警告:

如果服务器上当前正在执行工作负载,则对sys.dm_exec_query_stats的初始查询可能会产生不准确的结果。可以通过重新运行查询来确定更准确的结果。

此外,我不确定 的值如何last_execution_time受到跨多个会话的完全相同 SQL 的多次并发执行的影响,因为sys.dm_exec_query_stats是每个查询批处理,而不是每个会话。

以下是我到目前为止所拥有的。也许我有点想清理一件事,但这应该已经说明了批处理中的第一个查询,该查询不会有相应的条目,sys.dm_exec_query_stats因为它在当前之后被填充(理想情况下,但并不总是及时)语句/查询完成。它似乎适用于单查询批处理,所以试试吧。

SELECT req.session_id AS [SessionID],
       req.start_time AS [BatchStartTime],
       req.total_elapsed_time as [BatchMilliseconds], --[TotalElapsedTimeMs],
       CASE WHEN stat.last_execution_time IS NOT NULL THEN
                DATEADD(MILLISECOND,
                        (stat.last_elapsed_time / 1000.0),
                        stat.last_execution_time)
            ELSE req.start_time END AS [StatementStartTime],
       DATEDIFF(MILLISECOND,
                CASE WHEN stat.last_execution_time IS NOT NULL THEN
             DATEADD(MILLISECOND, (stat.last_elapsed_time / 1000.0),
                stat.last_execution_time)
                  ELSE req.start_time END, GETDATE()) AS [StatementMilliseconds],
       T2.login_name AS [LoginName],
       req.command AS [SQLCommand],
       req.[status] AS [QueryStatus],
       req.wait_type AS [WaitType],
       req.wait_time AS [WaitTimeMs],
       blocking_session_id AS [BlockingSessionId],
       req.row_count AS [RowCount],
       req.cpu_time AS [CpuTimeMs],
       sqltext.[text] AS [QueryBatch],
       SUBSTRING(sqltext.[text],
                 req.statement_start_offset / 2,
                 CASE req.statement_end_offset
                      WHEN -1 THEN DATALENGTH(sqltext.[text])
                      ELSE (req.statement_end_offset - req.statement_start_offset) / 2
                 END) AS [CurrentQuery]
FROM sys.dm_exec_requests req
INNER JOIN sys.dm_exec_sessions T2
        ON T2.session_id = req.session_id
LEFT JOIN sys.dm_exec_query_stats stat
        ON stat.[sql_handle] = req.[sql_handle]
       AND stat.statement_end_offset = (req.statement_start_offset - 2)
CROSS APPLY sys.dm_exec_sql_text(req.[sql_handle]) sqltext
-- WHERE req.session_id = 56
ORDER BY req.start_time;
Run Code Online (Sandbox Code Playgroud)

我已与您的查询(略有修改)测试和下面的SQL在另一个选项卡/会话中运行(在TOP(1)TOP(2)等,以及10.110.2在等WAITFOR时间,使之很容易看到其中的语句正在处理查看当前时语句字段):

SELECT GETDATE() AS [StartTime];
GO
SELECT TOP(1) [name] FROM sys.objects;
WAITFOR DELAY '00:00:10.1';

SELECT TOP(2) [name] FROM sys.objects;
WAITFOR DELAY '00:00:10.2';

SELECT TOP(3) [name] FROM sys.objects;
WAITFOR DELAY '00:00:10.3';

SELECT TOP(4) [name] FROM sys.objects;
WAITFOR DELAY '00:00:10.4';
Run Code Online (Sandbox Code Playgroud)

然后只需多次运行您的查询,很明显,dm_exec_requests.start_timedm_exec_sessions.last_request_start_time是:

  • 相同的值,并且
  • 在执行该批处理期间根本不更改。

我确实尝试通过 获取执行计划CROSS APPLY sys.dm_exec_text_query_plan(req.plan_handle, req.statement_end_offset, req.statement_end_offset) tplan,但这NULL并不是很有帮助。


为了测试您的查询,我必须删除前两列和对该dbo.GetExecutingSQLStatement函数的引用。这可能是您也可以摆脱的,因为您已经通过CROSS APPLY sys.dm_exec_sql_text(req.[sql_handle]). 您只需要进行以下三项更改:

  • T3.FullStatement (选择字段#1)变成 sqltext.[text]

  • T3.ExecutingStatement (选择字段#2)变成 SUBSTRING(sqltext.[text], req.statement_start_offset / 2, CASE req.statement_end_offset WHEN -1 THEN LEN(sqltext.[text]) ELSE (req.statement_end_offset - req.statement_start_offset) / 2 END)

  • 删除SUBSTRING(您当前的最后一个字段)。如果您仔细查看SUBSTRING我直接在上面建议的内容,它本质上就是您最后所拥有的内容,希望它可以纠正两个错误:

    • 您SUBSTRING没有考虑时,只有1批次查询,在这种情况下statement_end_offset-1和你的子得到一个错误
    • 您的 SUBSTRING 没有考虑将双字节字节数转换为字符数。

但我离题了。