Solved

Need to tweak sql query

Posted on 2011-02-16
3
475 Views
Last Modified: 2012-05-11
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%';
0
Comment
Question by:hraja77
  • 2
3 Comments
 
LVL 7

Accepted Solution

by:
tlovie earned 500 total points
ID: 34908419
you could create a stored procedure that would do something like this and run it in a job:

create procedure spPCMS_SQL_CACHE as

declare @timestamp datetime
select @timestamp=getdate()

INSERT INTO pcms_sql_cache
SELECT TOP 1
   @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%';


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

Author Comment

by:hraja77
ID: 34908553
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
0
 
LVL 7

Expert Comment

by:tlovie
ID: 34908620
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
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

PL/SQL can be a very powerful tool for working directly with database tables. Being able to loop will allow you to perform more complex operations, but can be a little tricky to write correctly. This article will provide examples of basic loops alon…
This article describes how to use the timestamp of existing data in a database to allow Tableau to calculate the prior work day instead of relying on case statements or if statements to calculate the days of the week.
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now