使用 SSDT 创建图表以显示始终有多少工作 运行

Creating a chart with SSDT to show how many jobs are running at all times

我正在尝试绘制一个 chart/graph 来显示一天中任何给定时间有多少工作 运行,当工作开始时很容易,但想法是它应该显示它需要多长时间。

我有一个贯穿所有作业的查询,获取它们的开始时间、持续时间,如果需要的话,我已经计算了结束时间,但我似乎无法将其显示在人们的屏幕上能够去,哦,是的,这里有 5 个长期 运行 工作,none 这里。

大多数工作几乎不需要时间,但我们确实有一些工作需要几分钟,还有一些需要一夜之间完成,可能需要一个多小时。

我用来获取信息的基本代码:

    WITH CTE as(
        select run_duration
        ,cast(concat(cast(run_date as varchar(8)),' ',substring(right('00000'+cast(run_time as varchar(8)),6),1,2),':',
            substring(right('000'+cast(run_time as varchar(6)),4),1,2),':',
            substring(right(run_time,2),1,2))as datetime) as [starttime]
        FROM msdb.dbo.sysjobhistory WITH (NOLOCK)
        WHERE run_duration >0
    )
    SELECT 1 as [running],run_duration,starttime,DATEADD(ss,run_duration,[starttime]) AS [endTime]
    FROM CTE 
    WHERE  [starttime] > (GETUTCDATE() - 1)
    ORDER BY [starttime] DESC

任何关于我应该如何处理的帮助/线索将不胜感激(如果需要,可以创建一个单独的管理员 table。

已将 link 附加到图像中,这是我所追求的一个非常粗略的想法 http://stephen-bov.co.uk/images/JobsRunning.png

谢谢 Ste

* 请参阅其他最终实施答案 * 设法让它工作, 它有点乱,但如果有人在

,这里是代码
WITH CTE AS(
    SELECT run_duration, instance_ID
    --,msdb.dbo.agent_datetime(run_date,run_time) as startingtime
    ,cast(concat(cast(run_date as varchar(8)),' ',substring(right('00000'+cast(run_time as varchar(8)),6),1,2),':',
        substring(right('000'+cast(run_time as varchar(6)),4),1,2),':',
        substring(right(run_time,2),1,2))as datetime) as [startingtime]
    FROM msdb.dbo.sysjobhistory WITH (NOLOCK)
    WHERE run_duration >0
), Pri AS
(
SELECT 1 as running,run_duration, instance_ID, startingtime
FROM CTE 
WHERE  [startingtime] > (GETUTCDATE() - 1)

)

SELECT distinct(p1.startingtime), count(p1.running) AS [running] FROM Pri p1
LEFT JOIN PRI p2 ON 
    p1.startingtime between p2.startingtime and DATEADD(ss,p2.run_duration,p2.[startingtime])
GROUP BY p1.startingtime,p1.instance_id
order by startingtime

我只关注了至少需要一秒钟才能完成的作业 运行(否则真的很乱。

当工作结束时,仍有工作要做以刷新列表,但有工作运行现在足够频繁以获得粗略视图,

新的代码改进,现在考虑了仍然是 运行 的工作,以及仍然是 运行 但在 date-1 之前开始的工作 (也运行得更快)

IF OBJECT_ID('tempdb..#jobtimes') IS NOT NULL
   DROP TABLE #jobtimes
IF OBJECT_ID('tempdb..#jobhis') IS NOT NULL
   DROP TABLE #jobhis

SELECT instance_ID
    ,(substring(right('00000'+cast(run_duration as varchar(8)),6),1,2)*60*60) +
        (substring(right('000'+cast(run_duration as varchar(6)),4),1,2)*60) +
        substring(right(run_duration,2),1,2)
        as run_duration
    ,cast(concat(cast(run_date as varchar(8)),' ',substring(right('00000'+cast(run_time as varchar(8)),6),1,2),':',
        substring(right('000'+cast(run_time as varchar(6)),4),1,2),':',
        substring(right(run_time,2),1,2))as datetime) as [startingtime]
    INTO #jobhis
   FROM msdb.dbo.sysjobhistory WITH (NOLOCK) 
   WHERE 
run_duration >0 and
step_id = 0 and
cast(run_date as varchar(8)) > (GETDATE() - 2 )
    UNION
SELECT 1,datediff(second,start_execution_date,GETdate()),start_execution_date 
    FROM msdb.dbo.sysjobactivity with(nolock) 
    WHERE run_requested_date is not null 
        and stop_execution_date is null 
        and start_execution_date > GETUTCDATE()-2


SELECT 1 as running,run_duration, instance_ID, startingtime, dateadd(ms,-10,DATEADD(ss,run_duration,startingtime)) as endtime
        into #jobtimes
    FROM #jobhis
    WHERE  dateadd(ms,-10,DATEADD(ss,run_duration,startingtime)) > (GETDATE() -1)
UNION 
SELECT NULL as running ,0 as run_duration, 0 as instance_ID, DATEADD(ss,run_duration,startingtime) as startingtime, NULL as endtime
    FROM #jobhis
    WHERE  [startingtime] > (GETDATE() - 1 )

SELECT p1.startingtime,count(p2.running) as instances 
    FROM #jobtimes p1
        LEFT JOIN #jobtimes p2 ON 
            p2.running =1 
            AND p1.startingtime between  p2.startingtime and p2.endtime
    WHERE p1.startingtime > (getdate()-1)
    GROUP BY p1.startingtime,p1.run_duration

DROP TABLE #jobtimes

DROP TABLE #jobhis

旧答案供参考

更新能够检测每个作业的结束,因此一旦所有作业都完成,图形将下降到 0,或者只是下降到一个完成后还剩下多少,

我们每天有 27k 个作业 运行 至少需要一秒钟 运行 直接在管理工作室中进行查询大约需要一分半钟,运行 在 SSDT 中它用时不到 10 秒(不知道它是否缓存了很多信息)

 WITH CTE AS(
    SELECT instance_ID
    ,(substring(right('00000'+cast(run_duration as varchar(8)),6),1,2)*60*60) +
        (substring(right('000'+cast(run_duration as varchar(6)),4),1,2)*60) +
        substring(right(run_duration,2),1,2)
        as run_duration
    --,msdb.dbo.agent_datetime(run_date,run_time) as startingtime
    ,cast(concat(cast(run_date as varchar(8)),' ',substring(right('00000'+cast(run_time as varchar(8)),6),1,2),':',
        substring(right('000'+cast(run_time as varchar(6)),4),1,2),':',
        substring(right(run_time,2),1,2))as datetime) as [startingtime]
    FROM msdb.dbo.sysjobhistory WITH (NOLOCK) 
    WHERE run_duration >0 and cast(run_date as varchar(8)) > (GETUTCDATE() - 2 )
), Pri AS
(
SELECT 1 as running,run_duration, instance_ID, startingtime, dateadd(ms,-10,DATEADD(ss,run_duration,startingtime)) as endtime
FROM CTE 
WHERE  [startingtime] > (GETUTCDATE() - 1 )
UNION 
SELECT NULL as running ,0 as run_duration, 0 as instance_ID, DATEADD(ss,run_duration,startingtime) as startingtime, NULL as endtime
FROM CTE 
WHERE  [startingtime] > (GETUTCDATE() - 1 )
)
SELECT p1.startingtime,count(p2.running) as instances FROM Pri p1
LEFT JOIN Pri p2 ON 
    p2.running =1 AND p1.startingtime between  p2.startingtime and p2.endtime
    GROUP BY p1.startingtime,p1.run_duration
order by startingtime

希望其他任何想看这篇文章的人都会觉得有用

Ste