Quantcast
Channel: SQLServerCentral » SQL Server 2014 » Administration - SQL Server 2014 » Latest topics
Viewing all articles
Browse latest Browse all 6525

Another sysjobhistory query

$
0
0
For many years I've wanted to be able to visualize how long my SQL Agent jobs are taking to run over time. I've wanted to see them both as a total duration of the job and broken down by each step. I've seen some tools (some free some paid) that get close but none that give me exactly what I want. I've also tried to write queries using sysjobs and sysjobhistory to pull out the data that I want but infuriatingly there is no way straight forward way to tie the execution of steps in sysjobhistory to each other. What I mean by this is that there is a job_id field linking it to a job but nothing linking it to an execution of that job. A human can easily look at execution times, etc and see which steps go with what executions but that's not good enough if you want to visualize your executions on a graph, etc.Today I scoured the internet again and came up with nothing so I buckled down and came up with a solution myself. I was able to tie a step to it's siblings by calculating the begin and end times of a job execution and then assuming if a step's execution falls in this time frame then it's part of the same job's execution. Be warned, this query can take some time to run (15 minutes on my production server). If you filter it to one job it runs much quicker. Because of this I used NOLOCK to not lock the tables so if you have jobs that are currently running you may get odd results.A key point about sysjobhistory is that if the step_id is 0 then the row represents the execution of the whole job. If the step_id is not 0 then it's one of the individual steps. I use this to build a list of executions in a CTE calculating the begin and end date/time. I then join back to sysjobhistory getting the details of each step. If you only care about the info for the job execution as a whole just use the CTE by itself, no need to join back to sysjobhistory for the step details.I use several tricks about getting run_date, run_time, run_duration and run_status into a usable form that I won't get into the details. You can search the internet on these field names and find lots of discussions if you are interested. The only thing I'll mention about this is that I could not use agent_datetime on run_duration because I have jobs that took more than 24 hours and that blew up agent_datetime.I use the FORMAT command so this is only going to work in SQL 2012+. I also use the undocumented dbo.agent_datetime and I'm not sure when MS added that to MSDB. To use it in older versions you may have to figure out how to replace those two functions.Be warned that JobInstanceNumber is just a row number counter and will change between executions of the query, you can't use it as a key to store off the data and refer to it later. I have it in the query to make creating the visualizations simpler.I really only got this working today so there may be some issues with it that I haven't discovered, feel free to help me debug it if that is the case.[code="sql"]WITH JobInstance AS ( SELECT JobID = j.job_id , JobName = j.name , JobInstanceNumber = ROW_NUMBER() OVER(ORDER BY j.job_id,h.run_date,h.run_time) , JobInstanceStartDateTime = dbo.agent_datetime(h.run_date,h.run_time) , JobInstanceDuration = FORMAT(run_duration,'00:00:00') , JobInstanceDurationSeconds = run_duration/10000*3600 + run_duration/100%100*60 + run_duration%100 , JobInstanceEndDateTime = DATEADD(second, run_duration/10000*3600 + run_duration/100%100*60 + run_duration%100, dbo.agent_datetime(h.run_date,h.run_time) ) , JobInstanceStatus = CASE h.run_status WHEN 0 THEN 'Failed' WHEN 1 THEN 'Succeeded' WHEN 2 THEN 'Retry' WHEN 3 THEN 'Cancelled' WHEN 4 THEN 'In Progress' END , JobInstanceMessage = h.message FROM sysjobhistory AS h INNER JOIN sysjobs AS j ON j.job_id = h.job_id WHERE 1=1 AND h.step_id = 0 )SELECT ji.* , StepID = h.Step_ID , StepName = h.step_name , StepStartDateTime = dbo.agent_datetime(h.run_date,h.run_time) , StepDuration = FORMAT(run_duration,'00:00:00') , StepDurationSeconds = run_duration/10000*3600 + run_duration/100%100*60 + run_duration%100 , StepEndDateTime = DATEADD(second, run_duration/10000*3600 + run_duration/100%100*60 + run_duration%100, dbo.agent_datetime(h.run_date,h.run_time) ) , StepStatus = CASE h.run_status WHEN 0 THEN 'Failed' WHEN 1 THEN 'Succeeded' WHEN 2 THEN 'Retry' WHEN 3 THEN 'Cancelled' WHEN 4 THEN 'In Progress' END , StepMessage = h.messageFROM JobInstance ji WITH (NOLOCK) INNER JOIN sysjobhistory h WITH (NOLOCK) ON ji.JobID = h.job_id AND dbo.agent_datetime(h.run_date,h.run_time) BETWEEN ji.JobInstanceStartDateTime and ji.JobInstanceEndDateTime AND h.step_id <> 0ORDER BY JobName, JobInstanceStartDateTime,h.step_id[/code]

Viewing all articles
Browse latest Browse all 6525

Trending Articles