新到一家公司,需要折腾点认可出来。然后开始苦逼的优化工作~
优化效果
优化前,作业历史记录(前20)
按作业执行时长优化
优化前,CPU使用情况
按作业执行时长优化
有几个作业平均时长2.5~3.5小时,还有很多时长在半小时以上的作业,基本要到11-12点才能完成作业统计。CPU每天7:00-11:00一直维持在比较高的数值。
优化后,作业历史记录(前20)
按作业执行时长优化
最近三天的CPU情况
按作业执行时长优化
最近一天的CPU情况
按作业执行时长优化
优化后,作业执行时长明显降低,从最近3天执行情况看,9:00前统计作业能够执行完成。服务器CPU高峰时段由之前的7:00-11:00降到现在7:00-8:30。
优化步骤
由于问题很明确,降低作业执行时长!3个小时、4个小时太长,降低!有多低降多低!所以就直奔主题,针对作业、作业涉及语句/存储过程进行优化!所以这里第一步没有去取worker_time或者logical_reads消耗高的语句/存储过程。
1、提取作业历史记录,按平均执行时间倒序,优先处理执行时间最长的作业
第一个作业往往只能从执行计划查看缺失的索引、以及高消耗的操作,结合set statistics io on得到每步操作的reads情况,大致就能定位到高消耗的语句。大部分是缺少索引,对表进行扫描,这种情况下创建合适索引即可。另一种情况需要对存储过程进行修改,表后面加/删索引提示,语句后面添加重编译选项,关联查询指定联接方式,借助临时表保存多次使用的数据,以改善执行计划的选择。
往往优化完一个作业后,会发现部分其他作业也得到提升。其一、它们使用了相同的表,查询条件也类似,可以从之前的索引中获益。会存在这种情况,后续优化过程中需要调整之前创建好的索引,综合考虑相关的操作,创建一个相对通用的索引。其二、前面的作业优化后,消耗降低。系统有更多的资源来处理后续作业,性能会有适当的提升。

--最近7天作业执行时长
select top 1000 a.name
,isnull(b.JobRunTimes,0) JobRunTimes
,convert(varchar,isnull(b.FirstRunDateTime,0),120) FirstRunDateTime
,convert(varchar,isnull(b.LastRunDateTime,a.LastRunDateTime),120) LastRunDateTime
,isnull(right('00'+convert(varchar,b.AvgRunDuration/3600),2)+':'
+right('00'+convert(varchar,b.AvgRunDuration%3600/60),2)+':'
+right('00'+convert(varchar,b.AvgRunDuration%60),2),a.LastRunDuration) AvgRunDuration
,a.LastRunDuration,isnull(b.JobRunTimes,0)*(a.StepCount+1) HistoryRecords 
from (
select sj.name,count(sjs.step_id) StepCount
,msdb.dbo.agent_datetime(sjv.last_run_date,sjv.last_run_time) LastRunDateTime
,convert(varchar,msdb.dbo.agent_datetime('20151201',sjv.last_run_duration),108) LastRunDuration
from msdb.dbo.sysjobs sj
inner join msdb.dbo.sysjobsteps sjs
on sj.job_id=sjs.job_id
inner join msdb.dbo.sysjobservers sjv
on sj.job_id=sjv.job_id
where sj.enabled=1
and sjv.last_run_date>0
group by sj.name,sjv.last_run_date,sjv.last_run_time,sjv.last_run_duration) a
left join (
SELECT sj.name,count(sj.name) JobRunTimes
,min(msdb.dbo.agent_datetime(run_date,run_time)) FirstRunDateTime --05及以上版本可直接调用msdb.dbo.agent_datetime
,max(msdb.dbo.agent_datetime(run_date,run_time)) LastRunDateTime
,avg(left(right('000000'+convert(varchar,sjh.run_duration),6),2)*3600
+substring(right('000000'+convert(varchar,sjh.run_duration),6),3,2)*60
+right(right('000000'+convert(varchar,sjh.run_duration),6),2)) AvgRunDuration
FROM  msdb.dbo.sysjobhistory sjh with(nolock)
INNER JOIN msdb.dbo.sysjobs sj
ON sjh.job_id=sj.job_id
WHERE sjh.step_id=0 AND sj.enabled=1
and msdb.dbo.agent_datetime(run_date,run_time)>=CONVERT(varchar,GETDATE()-6,112) --限制查看最近7天的记录
GROUP BY sj.name,sj.job_id
) b
on a.name=b.name
order by a.LastRunDuration desc,a.name
View Code

相关文章:

  • 2021-11-20
  • 2022-12-23
  • 2021-12-28
  • 2021-06-02
  • 2022-12-23
  • 2021-12-23
  • 2022-12-23
  • 2021-06-14
猜你喜欢
  • 2022-02-18
  • 2021-12-13
  • 2022-02-02
  • 2021-11-30
  • 2021-07-03
  • 2022-12-23
相关资源
相似解决方案