0

我尝试捕获一些用于记录目的的统计参数。“SET 参数”没有选项(即设置统计时间)。

所以我试图查询一些DMV:

select '3AAAAAAAAAAA';
--no GO-statement here

select 
    total_worker_time/execution_count AS [Avg CPU Time],
    total_elapsed_time as [Elapsed Time],
    total_rows as [Total rows],
    st.text,
    (select cast(text as varchar(4000)) from ::fn_get_sql((select sql_handle from sys.sysprocesses where spid = @@spid)))
from sys.dm_exec_query_stats AS qs
cross apply sys.dm_exec_sql_text(qs.sql_handle) AS st
--where  ???
order by creation_time desc

这里捕获的信息几乎是我需要的 - 但是:

该查询仅在 DMV 的结果中列出,当它在最后执行的 GO-Block 中运行时(不是在实际中)。这不是我需要的。我需要@@error 或@@rowcount 之类的东西在同一个GO 块中可用并保存经过的时间和CPU 时间。任何想法如何查询最后一条语句的信息?

如果可以解决:我想查询会话(@@spid)中的“最后一个”语句执行,而无需两次编写语句。


问题更新:

此查询正在“按会话”运行,并将列出请求的值(尽管缺少琐碎的查询)。Top 1 总是会带回最后一个 Statement 的值(如果通过 exec @SQL 触发则不会产生另一个会话):

print 'hello';

select top 10 'my personal identifier: 1', * FROM sys.messages;

select top 20 'my personal identifier: 2', * FROM sys.messages;

print 'hello';
select 'hello';

select top 30 'my personal identifier: 3', * FROM sys.tables;

select top 1
    total_worker_time/execution_count AS [Avg CPU Time],
    total_elapsed_time as [Elapsed Time],
    total_rows as [Total rows],
    substring(st.text, (qs.statement_start_offset / 2) + 1, (case when qs.statement_end_offset = -1 then datalength(st.text) else qs.statement_end_offset end - qs.statement_start_offset ) / 2 + 5) as [executing statement] 
from sys.dm_exec_query_stats AS qs
cross apply sys.dm_exec_sql_text(qs.sql_handle) AS st
where st.text = (select cast(text as varchar(4000)) from ::fn_get_sql((select sql_handle from sys.sysprocesses where spid = @@spid)))
order by qs.statement_start_offset desc;

过滤器(where 子句)似乎很粗糙,而且不是很健壮。有什么办法可以改善这一点吗?

4

1 回答 1

0

我试着回答自己(Jeroen Mostert - 非常感谢你的帮助!) - 这个问题没有答案(见下文):

如果语句足够复杂以调用 SQL 计划生成,则以下函数应为您提供 CPU、执行时间、I/O、实际会话中执行的最后一条语句的数量或行数。也就是说,在简单的打印命令之后,结果集将是 enpty。即使在执行存储过程之后如果他们打开一个新会话(即在 exec sp_executesql 之后结果集将为空)。

对于“平均”SQL 语句,以下查询应生成一个行集,其中包含您将通过 set statistice time on 和 set statistice io on 获得的信息。

drop function if exists dbo.ufn_lastsql_resources ;
go

CREATE FUNCTION dbo.ufn_lastsql_resources (@session_id int)
RETURNS TABLE  
AS  
return
select 
    top 1

    convert(char(10), getdate(), 121) + ' ' + substring(convert(char(40), getdate(), 121), 12,12) + ',' as [Time stamp], 
    cast(cast((last_worker_time / execution_count / 1000. ) as numeric(9,2)) as varchar(100)) + ','     as [Avg CPU Time in ms],
    cast(cast((last_elapsed_time / 1000. ) as numeric(9,2)) as varchar(100)) + ','                      as [Elapsed Time in ms],
    cast(last_rows as varchar(100)) + ','                                                               as [Total rows],
    cast(substring(st.text, (statement_start_offset / 2) + 1, (case when statement_end_offset = -1 then datalength(st.text) else statement_end_offset end - statement_start_offset ) / 2 + 2) as varchar(4000)) + ',' 
                                                                                                        as [executing statement],

    last_physical_reads + last_logical_reads                                                            as [Reads],
    last_logical_writes                                                                                 as [Writes],

    --last_grant_kb,
    --last_used_grant_kb,
    --last_ideal_grant_kb,

    --last_reserved_threads,
    --last_used_threads

    @session_id                                                                                         as spid

from 
    (
    select qs.*
    from sys.dm_exec_query_stats as qs
    inner join sys.dm_exec_requests as eq 
    on  qs.sql_handle  = eq.sql_handle
    and qs.plan_handle = eq.plan_handle 
    and eq.session_id  = @session_id
    ) a
cross apply sys.dm_exec_sql_text(a.sql_handle) AS st
where 
    substring(st.text, (statement_start_offset / 2) + 1, (case when statement_end_offset = -1 then datalength(st.text) else statement_end_offset end - statement_start_offset ) / 2 + 2) not like '%ufn_lastsql_resources%'
order by 
    last_execution_time desc, statement_start_offset desc
go

很可能有更优雅的方法可以做到这一点。也许即使使用使用选项(重新编译)或执行(@sql)的语句也可以编写一些可以正常工作的东西无论如何:我似乎在 SQL Server 2016 和 2012 上工作。您需要在服务器上获得 VIEW SERVER STATE 权限. 要调用该函数,请尝试:

drop table if exists #t1
select top 10 'statement 1' a, * into #t1 from sys.messages
select 1, * from dbo.ufn_lastsql_resources(@@spid) option (recompile)


drop table if exists #t2
select top 20 'statement 2' a, * into #t2 from sys.messages 
--select 2, * from dbo.ufn_lastsql_resources(@@spid)

select top 3 'statement 3' a, * from sys.messages 
select 3, * from dbo.ufn_lastsql_resources(@@spid) option (recompile)

这个问题没有得到解答,因为方法不正常。不确定从批处理中捕获正确的语句(会话中按 last_execution 时间排序的前 1 个和批处理中的最后一个。这似乎是错误的顺序。由于计划被重用,这是唯一的方法,我想通了去工作。)

于 2018-01-24T12:43:20.227 回答