Why do you care about job run times and why do you need to archive it? Job run times are very important piece of information used for measuring the performance of a database. There are other variables used for measuring the performance as well and job run times is one I use frequently to see if any jobs are taking longer.
Most database management systems today store the job run time in their system tables or views. With SQL Server, you can only go back to 15 days. Similarly, ORACLE and other DBMS have some cut off on how long to store it. Sometime two weeks worth of data isn't enough to find a trend. Will you see your job in a history table that runs monthly or quarterly? No, you don't!
How are you going to store the run time statistics beyond two weeks?
Job that runs monthly or quarterly may not be in a job history table, therefore I would like to write my own custom process to store stats past 15 days. In order to get a solid result, I would like to keep it for last 6 months. Keeping 6 months old history is enough to capture daily, monthly and quarterly jobs.
With this blog, I will show step-by-step instructions on how to store last six month's worth of job history data.
Let's being by creating a table.
Create Table
Create Procedure:
This procedure does two things: Inserts job details to a table and then purge data older then 6 months.
Schedule a Job:
Now, you are required to schedule a job to run the procedure we created. This job should be schedule to run once daily. The job should execute the procedure as shown below.
How to Analyzed Data?
We have a job that runs daily to collected the stats about the job. Now, we need to analyze the data we collected to see if there’s a downward of upward pattern? If you see the run times going up, then that is a red flag. You will need to dive into the detail about the job to find out why it is taking longer each day, week or month?
The query below will give you the average time taken in seconds and in minutes for each jobs. You also have the flexibility to run for a specific time frame. I will like to run the query for each month interval and look for pattern.
What if you are to analyze with whatever stats you have in job history table? If you are OK with last 15 days worth of data, then the query below will show you the total run time for each jobs in minutes and seconds. SQL Server Job history table stores run duration in "hhmmss" format, which I converted to total seconds and in total minutes.Try it out!
Most database management systems today store the job run time in their system tables or views. With SQL Server, you can only go back to 15 days. Similarly, ORACLE and other DBMS have some cut off on how long to store it. Sometime two weeks worth of data isn't enough to find a trend. Will you see your job in a history table that runs monthly or quarterly? No, you don't!
How are you going to store the run time statistics beyond two weeks?
Job that runs monthly or quarterly may not be in a job history table, therefore I would like to write my own custom process to store stats past 15 days. In order to get a solid result, I would like to keep it for last 6 months. Keeping 6 months old history is enough to capture daily, monthly and quarterly jobs.
With this blog, I will show step-by-step instructions on how to store last six month's worth of job history data.
- Create a Table
- Create a Procedure
- Schedule a Job
- Analyze Data
Let's being by creating a table.
Create Table
USE [Your DB] GO /****** Object: Table [dbo].[job_run_times] Script Date: 12/01/2014 09:43:34 AM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[job_run_times]( [name] [sysname] NOT NULL, [run_status] [int] NOT NULL, [durationHHMMSS] [varchar](8000) NULL, [start_date] [datetime] NULL ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO
Create Procedure:
This procedure does two things: Inserts job details to a table and then purge data older then 6 months.
CREATE PROCEDURE sp_job_run_times AS -- Inserting run time STATS of all the jobs to job_run_times table INSERT INTO [Your DB].dbo.job_run_times SELECT j.NAME, h.run_status, durationHHMMSS = Stuff(Stuff(Replace(Str(h.run_duration, 7, 0), ' ', '0') , 4, 0, ':'), 7, 0, ':'), [start_date] = CONVERT(DATETIME, Rtrim(run_date) + ' ' + Stuff(Stuff(Replace(Str(Rtrim(h.run_time), 6, 0), ' ', '0'), 3, 0, ':'), 6, 0, ':')) FROM msdb.dbo.sysjobs AS j INNER JOIN (SELECT job_id, instance_id = Max(instance_id) FROM msdb.dbo.sysjobhistory GROUP BY job_id) AS l ON j.job_id = l.job_id INNER JOIN msdb.dbo.sysjobhistory AS h ON h.job_id = l.job_id AND h.instance_id = l.instance_id ORDER BY CONVERT(INT, h.run_duration) DESC, [start_date] DESC --Purging data older than six month if any DECLARE @Retention_Date DATETIME = Dateadd(mm, -6, Getdate()) DELETE FROM [Your DB].[dbo].[job_run_times] WHERE start_date < @Retention_Date; GO
Schedule a Job:
Now, you are required to schedule a job to run the procedure we created. This job should be schedule to run once daily. The job should execute the procedure as shown below.
USE [Your-DB] GO DECLARE @RC int EXECUTE @RC = [dbo].[sp_job_run_times] GO
How to Analyzed Data?
We have a job that runs daily to collected the stats about the job. Now, we need to analyze the data we collected to see if there’s a downward of upward pattern? If you see the run times going up, then that is a red flag. You will need to dive into the detail about the job to find out why it is taking longer each day, week or month?
The query below will give you the average time taken in seconds and in minutes for each jobs. You also have the flexibility to run for a specific time frame. I will like to run the query for each month interval and look for pattern.
WITH MY_CTE(name, run_status, durationhhmmss, start_date) AS (SELECT name, run_status, durationhhmmss, start_date FROM [Periop-Stage].dbo.job_run_times WHERE start_date BETWEEN '20141114' AND '20141121') -- Add your own date range here SELECT name, Avg(( Cast(Substring(Replace(durationhhmmss, ':', ''), 1, 3) AS INT) * 60 * 60 + Cast (Substring(Replace(durationhhmmss, ':', ''), 4, 2) AS INT) * 60 + Cast ( Substring(Replace(durationhhmmss, ':', ''), 6, 2) AS INT) )) AS avg_seconds, Avg(( Cast(Substring(Replace(durationhhmmss, ':', ''), 1, 3) AS INT) * 60 * 60 + Cast (Substring(Replace(durationhhmmss, ':', ''), 4, 2) AS INT) * 60 + Cast ( Substring(Replace(durationhhmmss, ':', ''), 6, 2) AS INT) ) / 60) avg_min FROM MY_CTE GROUP BY name;
What if you are to analyze with whatever stats you have in job history table? If you are OK with last 15 days worth of data, then the query below will show you the total run time for each jobs in minutes and seconds. SQL Server Job history table stores run duration in "hhmmss" format, which I converted to total seconds and in total minutes.Try it out!
SELECT DISTINCT( curr.job_id ), curr.NAME, history.run_date, date_executed=CONVERT(DATETIME, CONVERT(VARCHAR(8), run_date)) + ' ' + Stuff(Stuff(RIGHT(1000000+run_time, 6), 3, 0, ':' ), 6, 0, ':'), secs_duration=run_duration / 10000 * 3600 + run_duration%10000 / 100 * 60 + run_duration%100, mins_durations =( ( run_duration / 10000 * 3600 + run_duration%10000 / 100 * 60 + run_duration%100 ) / 60 ) FROM msdb.dbo.sysjobhistory history LEFT JOIN msdb.dbo.sysjobs curr ON curr.job_id = history.job_id WHERE history.step_id = 0 --Job Outcome AND history.run_status = 1 ORDER BY curr.NAME, history.run_date;
Interested in working with me? I can be reached at pbaniya04[at]gmail.com for any questions, consulting opportunities or you may drop a line to say HELLO. Thank your again for visiting my blog and looking forward to serving you more.
Have a Database-ious Day!
Have a Database-ious Day!
No comments