编写Profiler查询

时间:2014-12-12 13:54:35

标签: sql sql-server sql-server-2008 tsql

我正在编写一个查询来模拟Sql Server Profiler,我的版本是Sql Server 2008我没有Sql Profiler而且我需要它,此时我得到了这个查询:

Use master
Go

Alter procedure dbo.NS_sp_profilerQuery
    @dbName sysname='',
    @userName sysname=Null,
    @hostName sysname=Null
As
Begin
    --Step 1. Declaration of variables.
    Declare @idDb Int=DB_ID(@dbName);
    Declare @Query Nvarchar(Max);

    --Step 2. SETTING THE query.
    Select @Query = N'Select '+
    N'idProceso=syp.spid,basedatos=DB_NAME(syp.dbid),usuario=syp.loginame,cpu,hostname,espera=lastwaittype,[bloqueadoPor]=blocked,Query=(Select text from ::fn_get_sql(syp.sql_handle)) '+
    N'From master.dbo.sysprocesses syp '+
    N'Where 1=1 '+
    (case when @idDb is null then '' else 'and syp.dbid='+Ltrim(Rtrim(Str(@idDb))) end)+
    (case when @userName is null then '' else ' and Ltrim(Rtrim(syp.loginame))='+Quotename(Ltrim(Rtrim(@userName)),Char(39)) end)+
    (case when @hostName is null then '' else ' and Ltrim(Rtrim(syp.hostname))='+Quotename(Ltrim(Rtrim(@hostName)),Char(39)) end);

    --Step 3. Query and return data.
    Exec(@Query);
End
Go

此查询在一个点上捕获所有内容,我的问题是: 捕获长时间发生的所有事情的最佳方法是什么?,制作循环? 你会建议什么?

2 个答案:

答案 0 :(得分:2)

使用单个查询来模拟探查器是不可能的。您将获得当前正在运行的查询的快照。如果您想查看需要很长时间才能运行的查询,这对您来说可能已经足够了,但在这种情况下,我宁愿建议您查看dmv sys.dm_exec_query_stats。通过这个,您可以检查哪些查询占用了大量资源或时间。

示例,包括查询计划:

-- List top 100 queries that has the highest average logical reads
select top (100) *
from sys.dm_exec_query_stats qs
  cross apply sys.dm_exec_query_plan(qs.plan_handle) p
order by cast(qs.total_logical_reads as float) / qs.execution_count desc;

有许多有趣的列可供选择。

如果您真的想要捕获所有已执行的查询,您应该查看扩展事件。您可以记录所需的查询,例如稍后可以检查的文件或环形缓冲区。设置它需要做一些工作,但官方的sql server文档提供了有关如何操作的很好的信息。

答案 1 :(得分:0)

此查询解决了我的需求,它可以工作99%,我将快照发送到dbo.sysprocesses。

Use master
Go

Alter procedure dbo.NS_sp_profilerQuery
    @dbName sysname='',
    @userName sysname=Null,
    @hostName sysname=Null,
    @Seconds int
As
Begin

    Declare @SnapShots Table(
    idProceso int,
    idThread int,
    basedatos sysname, 
    usuario sysname, 
    cpu int, 
    hostname sysname, 
    espera sysname, 
    bloqueadoPor int, 
    Query Nvarchar(Max)
);

Declare @Profiler Table(
    idProceso int,
    idThread int,
    basedatos sysname, 
    usuario sysname, 
    cpu int, 
    hostname sysname, 
    espera sysname, 
    bloqueadoPor int, 
    Query Nvarchar(Max)
);

--Paso 1. Declaración de variables.
Declare @idDb Int=DB_ID(@dbName);
Declare @Query Nvarchar(Max);
Declare @HoraFinal Datetime=DateAdd(Second,@Seconds,Getdate());

While Getdate()<=@HoraFinal
Begin
    --Paso 2. Seteo de consulta.
    Select @Query = N'Select '+
    N'idProceso=syp.spid,idThread=syp.kpid,basedatos=DB_NAME(syp.dbid),usuario=syp.loginame,cpu,hostname,espera=lastwaittype,[bloqueadoPor]=blocked,Query=(Select text from ::fn_get_sql(syp.sql_handle)) '+
    N'From master.dbo.sysprocesses syp '+
    N'Where 1=1 '+
    (case when @idDb is null then '' else 'and syp.dbid='+Ltrim(Rtrim(Str(@idDb))) end)+
    (case when @userName is null then '' else ' and Ltrim(Rtrim(syp.loginame))='+Quotename(Ltrim(Rtrim(@userName)),Char(39)) end)+
    (case when @hostName is null then '' else ' and Ltrim(Rtrim(syp.hostname))='+Quotename(Ltrim(Rtrim(@hostName)),Char(39)) end);

    --Paso 3. Consulta y retorno de datos.
    Insert Into @SnapShots(idProceso,idThread,basedatos,usuario,cpu,hostname,espera,bloqueadoPor,Query)
    Exec(@Query);

    Insert Into @Profiler(idProceso,idThread,basedatos,usuario,cpu,hostname,espera,bloqueadoPor,Query)
    Select 
        sna.idProceso,sna.idThread,sna.basedatos,sna.usuario,sna.cpu,sna.hostname,sna.espera,sna.bloqueadoPor,sna.Query 
    From @SnapShots sna
    Left Join @Profiler pro
        On (sna.idProceso=pro.idProceso and sna.idThread=pro.idThread)
    Where pro.idProceso is null;

    Delete From @SnapShots;
End

Select 
    idProceso,idThread,basedatos,usuario,cpu,hostname,espera,bloqueadoPor,Query
From @Profiler;

End
Go