Link to home
Create AccountLog in
Avatar of hraja77
hraja77

asked on

Need to tweak sql query

Hi,

I have a query which populates a table called pcms_sql_cache - the definition is below for the table;
The table gets populated by the query i have below;
What i need to do is run the sql hourly to populate the table from a sql job then raise an alert if the
column avg_recent_duration is greater than 5sec;
How should the sql be changed to run and check the column avg_recent_duration;
Please help - the sql looks worse than it is !

thanks

CREATE TABLE [dbo].[pcms_sql_cache](
      [ID] [int] IDENTITY(1,1) NOT NULL,
      [Timestamp] [datetime] NULL,
      [database_name] [varchar](20) NOT NULL,
      [statement_text] [varchar](5000) NOT NULL,
      [cache_creation_time] [datetime] NOT NULL,
      [total_execution_count] [bigint] NOT NULL,
      [total_cpu_time] [bigint] NOT NULL,
      [total_elapsed_time] [bigint] NOT NULL,
      [total_recent_time] [bigint] NULL,
      [total_recent_executions] [bigint] NULL,
      [avg_recent_duration] [bigint] NULL
) ON [PRIMARY]

INSERT INTO pcms_sql_cache
SELECT TOP 1
   GETDATE() as timestamp
   ,   DB_Name(qp.dbid) as database_name
   , SUBSTRING(qt.text, (qs.statement_start_offset/2) + 1,
        ((CASE statement_end_offset
            WHEN -1 THEN DATALENGTH(qt.text)
            ELSE qs.statement_end_offset END
                - qs.statement_start_offset)/2) + 1) as statement_text    
                , qs.creation_time as cache_creation_time
                , qs.execution_count
    , qs.total_worker_time as total_cpu_time
    , qs.total_elapsed_time
    , CASE WHEN (qs.total_elapsed_time - (select total_elapsed_time from pcms_sql_cache where ID=(select max(ID)from pcms_sql_cache))) >=0
      THEN  (qs.total_elapsed_time - (select total_elapsed_time from pcms_sql_cache where ID=(select max(ID)from pcms_sql_cache))) ELSE NULL END as total_recent_time
    , (qs.execution_count - (select total_execution_count from pcms_sql_cache where ID=(select max(ID) from pcms_sql_cache))) as

total_recent_executions
   , (qs.total_elapsed_time - (select total_elapsed_time from pcms_sql_cache where ID=(select max(ID)from pcms_sql_cache)))/    
   NULLIF((qs.execution_count - (select total_execution_count from pcms_sql_cache where ID=(select max(ID)from pcms_sql_cache))),0) as

avg_recent_duration
    FROM sys.dm_exec_query_stats as qs
    CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) as qp
    CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
     Where DB_Name(qp.dbid) = 'Autopart'
     and (SUBSTRING(qt.text, (qs.statement_start_offset/2) + 1,
        ((CASE statement_end_offset
            WHEN -1 THEN DATALENGTH(qt.text)
            ELSE qs.statement_end_offset END
                -qs.statement_start_offset)/2) + 1)) LIKE 'Select top 100%';
ASKER CERTIFIED SOLUTION
Avatar of tlovie
tlovie

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Avatar of hraja77
hraja77

ASKER

so far so good - but just aquick one - if the 'IF' statement is true i want to just make the sql server job fail - how would i do this ?

thanks
H
you'd have to change the if block to this:  


if exists (select * from pcms_sql_cache where timestamp=@timestamp and avg_recent_duration>5)
     begin
     exec MSDB.dbo.sp_send_dbmail @recipients='you@youremail.com;somebodyelse@youremail.com', @subject='Longer run times experienced', @body='whatever you want here'
     raiserror('Raiserror statement', 16, 1);
     end