SQLSERVER CPU占用过高的优化

news2024/12/23 5:39:54

有同事反应服务器CPU过高,一看截图基本都是100%了,my god,这可是大问题,赶紧先看看。

让同事查看系统进程,发现是SQLServer的CPU占用比较高。首先想到的是不是报表生成的时候高,因为这块之前出现过问题,关掉服务程序,还是高。难道是客户端程序引发的?但是这么多的客户端连接,难不成每个都叫人关闭,很简单,把网络断开即可。网络断开之后,CPU立马下降。那么问题到底在哪里呢,是时候祭出我们的利器了——SQLServer Profiler。

使用SQLServer Profiler监控数据库

让同事使用SQLProfiler监控了大概20分钟左右,然后保存为跟踪文件*.rtc。

我们来看看到底是哪句SQL有问题:

SQL1:查找最新的30条告警事件

select top 30  a.orderno,a.AgentBm,a.AlarmTime,a.RemoveTime,c.Name as AddrName,b.Name as MgrObjName,a.Ch,a.Value,a.Content,a.Level
    ,ag.Name as AgentServerName,a.EventBm,a.MgrObjId,a.Id,a.Cfmoper,a.Cfm,a.Cfmtime,a.State,a.IgnoreStartTime,a.IgnoreEndTime
    ,a.OpUserId,d.Name as MgrObjTypeName,l.UserName as userName,f.Name as AddrName2 
from eventlog as a left join mgrobj as b on a.MgrObjId=b.Id and a.AgentBm=b.AgentBm 
    left join addrnode as c on b.AddrId=c.Id left join mgrobjtype as d on b.MgrObjTypeId=d.Id 
    left join eventdir as e on a.EventBm=e.Bm left join agentserver as ag on a.AgentBm=ag.AgentBm 
    left join loginUser as l on a.cfmoper=l.loginGuid left join addrnode as f on ag.AddrId=f.Id 
where ((MgrObjId in (
    select Id from MgrObj 
    where AddrId in ('','02100000','02113000','02113001','02113002','02113003','02113004'
        ,'02113005','02113006','02113007','02113008','02113009','02113010','02113011','02113012'
        ,'02113013','02113014','02113015','02113016','02113017','02113018','02113019','02113020'
        ,'02113021','02113022','02113023','02113024','02113025','02113026'))) 
    or (mgrobjid in ('00000000-0000-0000-0000-000000000000','00000000-0000-0000-0000-000000000000'
        ,'00000000-0000-0000-0000-000000000000','11111111-1111-1111-1111-111111111111'
        ,'11111111-1111-1111-1111-111111111111'))
    ) 
order by alarmtime DESC

SQL2:获取当前的总报警记录数

select count(*)  from eventlog as a left join mgrobj as b on a.MgrObjId=b.Id and a.AgentBm=b.AgentBm 
    left join addrnode as c on b.AddrId=c.Id left join mgrobjtype as d on b.MgrObjTypeId=d.Id 
    left join eventdir as e on a.EventBm=e.Bm 
where MgrObjId in (
    select Id from MgrObj where AddrId in 
        ('','02100000','02100001','02100002','02100003','02100004','02100005','02100006','02100007'
        ,'02100008','02100009','02100010','02100011','02100012','02100013','02100014','02100015'
        ,'02100016','02100017','02100018','02100019','02101000','02101001','02101002','02101003'
        ,'02101004','02101005','02101006','02101007','02101008','02101009','02101010','02101011','02101012'
        ,'02101013','02101014','02101015','02101016','02101017','02101018','02101019','02101020','02101021'
        ,'02101022','02101023','02101024','02101025','022000','022001','022101','022102','0755','0755002')
    ) 
    and mgrobjid not in (
        '00000000-0000-0000-0000-000000000000','00000000-0000-0000-0000-000000000000','00000000-0000-0000-0000-000000000000'
        ,'11111111-1111-1111-1111-111111111111','11111111-1111-1111-1111-111111111111')

这是典型的获取数据并分页的数据,一条获取最新分页记录总数,一条获取分页记录,正是获取最新事件这里导致的CPU过高。这里的业务大概是每个客户端,每3秒执行一次数据库查找,以便显示最新的告警事件。好了,元凶找到了,怎么解决?

有哪些SQL语句会导致CPU过高?

上网查看了下文章,得出以下结论:

1.编译和重编译

编译是 Sql Server 为指令生成执行计划的过程。Sql Server 要分析指令要做的事情,分析它所要访问的表格结构,也就是生成执行计划的过程。这个过程主要是在做各种计算,所以CPU 使用比较集中的地方。

执行计划生成后会被缓存在 内存中,以便重用。但是不是所有的都可以 被重用。在很多时候,由于数据量发生了变化,或者数据结构发生了变化,同样一句话执行,就要重编译。

2.排序(sort) 和 聚合计算(aggregation)

在查询的时候,经常会做 order by、distinct 这样的操作,也会做 avg、sum、max、min 这样的聚合计算,在数据已经被加载到内存后,就要使用CPU把这些计算做完。所以这些操作的语句CPU 使用量会多一些。

3.表格连接(Join)操作

当语句需要两张表做连接的时候,SQLServer 常常会选择 Nested Loop 或 Hash 算法。算法的完成要运行 CPU,所以 join 有时候也会带来 CPU 使用比较集中的地方。

4.Count(*) 语句执行的过于频繁

特别是对大表 Count() ,因为 Count() 后面如果没有条件,或者条件用不上索引,都会引起 全表扫描的,也会引起 CPU 的大量运算

大致的原因,我们都知道了,但是具体到我们上述的两个SQL,好像都有上述提到的这些问题,那么到底哪个才是最大的元凶,我们能够怎么优化?

查看SQL的查询计划

SQLServer的查询计划很清楚的告诉了我们到底在哪一步消耗了最大的资源。我们先来看看获取top30的记录:

排序竟然占了94%的资源。原来是它!同事马上想到,用orderno排序会不会快点。先把上述语句在SQLServer中执行一遍,清掉缓存之后,大概是2~3秒,然后排序字段改为orderno,1秒都不到,果然有用。但是orderno的顺序跟alarmTime的顺序是不完全一致的,orderno的排序无法替代alarmTime排序,那么怎么办?我想,因为选择的是top,那么因为orderno是聚集索引,那么选择前30条记录,可以立即返回,根本无需遍历整个结果,那么如果alarmTime是个索引字段,是否可以加快排序?

选择top记录时,尽量为order子句的字段建立索引

先建立索引:

IF NOT EXISTS(SELECT * FROM sysindexes WHERE id=OBJECT_ID('eventlog') AND name='IX_eventlog_alarmTime')
    CREATE NONCLUSTERED INDEX IX_eventlog_alarmTime ON dbo.eventlog(AlarmTime)

在查看执行计划:

看到没有,刚才查询耗时的Sort已经消失不见了,那么怎么验证它能够有效的降低我们的CPU呢,难道要到现场部署,当然不是。

查看SQL语句CPU高的语句

SELECT TOP 10 TEXT AS 'SQL Statement'
    ,last_execution_time AS 'Last Execution Time'
    ,(total_logical_reads + total_physical_reads + total_logical_writes) / execution_count AS [Average IO]
    ,(total_worker_time / execution_count) / 1000000.0 AS [Average CPU Time (sec)]
    ,(total_elapsed_time / execution_count) / 1000000.0 AS [Average Elapsed Time (sec)]
    ,execution_count AS "Execution Count",qs.total_physical_reads,qs.total_logical_writes
    ,qp.query_plan AS "Query Plan"
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY total_elapsed_time / execution_count DESC

我们把建索引前后CPU做个对比:

已经明显减低了。

通过建立相关索引来减少表扫描

我们再来看看count(*)这句怎么优化,因为上面的这句跟count这句差别就在于order by的排序。老规矩,用查询计划看看。

用语句select count(0) from eventlog一看,该表已经有20多w的记录,每次查询30条数据,竟然要遍历这个20多w的表两次,能不耗CPU吗。我们看看是否能够利用相关的条件来减少表扫描。很明显,我们可以为MgrObjId建立索引:

CREATE NONCLUSTERED INDEX IX_eventlog_moid ON dbo.eventlog(MgrObjId)

但是无论我怎么试,都是没有利用到索引,难道IN子句和NOT IN子句是没法利用索引一定会引起表扫描。于是上网查资料,找到桦仔的文章,这里面有解答:

SQLSERVER对筛选条件(search argument/SARG)的写法有一定的建议

对于不使用SARG运算符的表达式,索引是没有用的,SQLSERVER对它们很难使用比较优化的做法。非SARG运算符包括

NOT、<>、NOT EXISTS、NOT IN、NOT LIKE和内部函数,例如:Convert、Upper等

但是这恰恰说明了IN是可以建立索引的啊。百思不得其解,经过一番的咨询之后,得到了解答:

不一定是利用索引就是好的,sqlserver根据你的查询的字段的重复值的占比,决定是表扫描还是索引扫描

有道理,但是我查看了下,重复值并不高,怎么会有问题呢。

关键是,你select的字段,这个地方使用索引那么性能更差,你select字段 id,addrid,agentbm,mgrobjtypeid,name都不在索引里。

真是一语惊醒梦中人,缺的是包含索引!!!关于包含索引的重要性我在这篇文章《我是如何在SQLServer中处理每天四亿三千万记录的》已经提到过了,没想到在这里又重新栽了个跟头。实践,真的是太重要了!

通过建立包含索引来让SQL语句走索引

好吧,立马建立相关索引:

IF NOT EXISTS(SELECT * FROM sysindexes WHERE id=OBJECT_ID('eventlog') AND name='IX_eventlog_moid')
    CREATE NONCLUSTERED INDEX IX_eventlog_moid ON dbo.eventlog(MgrObjId) INCLUDE(EventBm,AgentBM)

我们再来看看查询计划:

看到没有,已经没有eventlog表的表扫描了。我们再来比较前后的CPU:

很明显,这个count的优化,对查询top的语句依然的生效的。目前为止,这两个查询用上去之后,再也没有CPU过高的现象了。

其他优化手段

  • 通过服务端的推送,有事件告警或者解除过来才查询数据库。
  • 优化上述查询语句,比如count(*)可以用count(0)替代——参考《SQL开发技巧(二)》
  • 优化语句,先查询出所有的MgrObjId,然后在做连接
  • 为管理对象、地点表等增加索引
  • 添加了索引之后,事件表的插入就会慢,能够再怎么优化呢?可以分区建立索引,每天不忙的时候,把新的记录移入到建好索引的分区

当然,这些优化的手段是后续的事情了,我要做的事情基本完了。

总结

  • 服务器CPU过高,首先查看系统进程,确定引发CPU过高的进程
  • 通过SQLServer Profiler能够轻易监控到哪些SQL语句执行时间过长,消耗最多的CPU
  • 通过SQL语句是可以查看每条SQL语句消耗的CPU是多少
  • 导致CPU高的都是进行大量计算的语句:包括内存排序、表扫描、编译计划等。
  • 如果使用Top刷选前面几条语句,则尽量为Order By子句建立索引,这样可以减少对所有的刷选结果进行排序
  • 使用Count查询记录数时,尽量通过为where字句的相关字段建立索引以减少表扫描。如果多个表进行join操作,则把相关的表连接字段建立在包含索引中
  • 通过服务端通知的方式,减少SQL语句的查询
  • 通过表分区,尽量降低因为添加索引而导致表插入较慢的影响

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1652091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【WEEK11】 【DAY1】Employee Management System Part 2【English Version】

2024.5.6 Monday Continuing from 【WEEK10】 【DAY2】Employee Management System Part 1【English Version】 Contents 10.3. Page Internationalization10.3.1. Preparation10.3.2. Configuration File Writing10.3.2.1. Create an i18n (abbreviation for internationaliza…

iframe通信postMessage

iframe嵌入页面是实现微前端的方式之一。由于浏览器的跨域限制&#xff0c;iframe与父页面之间的通信变得不是那么容易。postMessage解决了这个问题。从广义上讲&#xff0c;一个窗口可以获得对另一个窗口的引用&#xff08;比如 targetWindow window.parent&#xff09;&…

增强for循环(for-each循环)

增强for循环&#xff08;for-each循环&#xff09;通常可以用于遍历实现Iterable接口的数据结构。Iterable接口定义了一个iterator()方法&#xff0c;该方法返回一个迭代器对象&#xff0c;用于遍历集合中的元素。 以下是一些常见的实现了Iterable接口的数据结构&#xff0c;可…

【大比武02】建设项目电子档案中的CA电子签名应用

关注我们 - 数字罗塞塔计划 - 应用CA电子签名取代手工签名和盖章是建设项目电子档案中可信存证的关键抓手。国内已有成熟应用的标杆性案例&#xff0c;如大湾区深中通道、广东惠清高速等。 然而&#xff0c;CA电子签名的必要性尚没有得到广泛认同&#xff0c;其应用过程中的问…

Charles抓包工具

Charles是一个HTTP代理工具&#xff0c;使开发人员能够查看客服端和服务器之间的所有HTTP/ HTTPS/SSL网络请求。 Charles是在PC环境下常用的网络抓包截取工具&#xff0c;在做移动开发时&#xff0c;我们为了调试客户端与服务端的网络通讯协议&#xff0c;常常需要截取网络请求…

【千帆平台】使用AppBuilder零代码创建应用,Excel表格数据转为Markdown格式文本

欢迎来到《小5讲堂》 这是《千帆平台》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言创建应用应用名称应用描述应用头像角色指令组件能力开场白推…

MouseBoost PRO mac中文激活版:专业鼠标助手

MouseBoost PRO mac鼠标性能优化软件&#xff0c;以其强大的功能和智能化的操作&#xff0c;助您轻松驾驭鼠标&#xff0c;提高工作效率。 MouseBoost PRO支持自定义快捷键设置&#xff0c;让您轻松实现快速切换应用程序、打开特定文件、调节音量大小等操作。自动识别窗口功能则…

【大前端】ECharts 绘制立体柱状图

立体柱状图分为&#xff1a; 纯色立体柱状图渐变立体柱状图 常用实现方式 纯色立体柱状图 纯色立体柱状图&#xff0c;使用MarkPoint和颜色渐变就实现&#xff0c;如下代码 import * as echarts from "echarts";var chartDom document.getElementById("main&…

基于Spring Ai 快速创建一个AI会话

文章目录 1、创建SpringBoot项目2、引入依赖3、修改配置文件4、一个简单的会话 前期准备 在OpenAI 注册页面创建帐户并在API 密钥页面生成令牌。 Spring AI 项目定义了一个配置属性&#xff0c;您应该将其设置为从 openai.com 获取的spring.ai.openai.api-key值 代码托管于gite…

终端安全管理措施有哪些?好用终端安全管理软件推荐(建议收藏)

在当今数字化时代&#xff0c;信息安全已成为企业运营不可或缺的一部分。其中&#xff0c;终端安全为您详细介绍&#xff0c;并推荐几款好用的终端安全管理软件&#xff0c;帮助您更好地保护企业信息安全。管理是确保企业信息安全的重要环节。那么&#xff0c;终端安全管理措施…

厂房环保水空调有多节能环保呢?

环保水空调确实具有显著的节能环保特点。其节能环保的优点主要体现在以下几个方面&#xff1a; 高效节能&#xff1a;环保水空调利用水的热传导和相变特性&#xff0c;通过水泵将冷热水循环运行&#xff0c;实现室内温度的控制。由于水具有较大的热容量&#xff0c;能够高效地…

【经验01】spark执行离线任务的一些坑

项目背景: 目前使用spark跑大体量的数据,效率还是挺高的,机器多,120多台的hadoop集群,还是相当的给力的。数据大概有10T的量。 最近在出月报数据的时候发现有一个任务节点一直跑不过去,已经超过失败次数的阈值,报警了。 预警很让人头疼,不能上班摸鱼了。 经过分析发现…

Java OOM问题排查

1.问题现象 tomcat web页面无法访问&#xff0c;日志报出如下错误&#xff0c; 问题出现频率 1晚上1次。 有时候会打印出oom的代码位置&#xff0c;有时候不会打印&#xff0c;不会打印则按照如下流程排查 2.问题排查过程 排查OOM主要是要获取内存的快照文件&#xff0c;但…

【CTF Web】攻防世界 GFSJ0478 cookie Writeup(HTTP协议+信息收集+Cookie)

cookie X老师告诉小宁他在cookie里放了些东西&#xff0c;小宁疑惑地想&#xff1a;‘这是夹心饼干的意思吗&#xff1f;’ 解法 按 F12&#xff0c;点击网络。 刷新页面。查看请求头中的 Cookie。 look-herecookie.php访问&#xff1a; http://61.147.171.105:53668/cookie.…

SpringBoot过滤器简单构建详细教程以及与拦截器区别解释

作用范围&#xff1a;过滤器基于Servlet规范&#xff0c;作用于更广泛的层面&#xff0c;不仅限于Spring MVC&#xff0c;它可以拦截进入Web应用的所有请求&#xff0c;包括静态资源请求。过滤器可以对请求和响应的内容进行预处理和后处理。实现方式&#xff1a;过滤器需要实现…

森林消防—高扬程水泵,高效、稳定、可靠!/恒峰智慧科技

森林&#xff0c;作为地球的“绿色肺叶”&#xff0c;不仅为我们提供了丰富的自然资源&#xff0c;更是维持生态平衡的重要一环。然而&#xff0c;随着全球气候的变化和人为活动的增加&#xff0c;森林火灾频发&#xff0c;给生态环境和人民生命财产安全带来了巨大威胁。在森林…

【C++历练之路】红黑树——map与set的封装实现

W...Y的个人主页&#x1f495; gitee代码仓库分享&#x1f60a; 前言&#xff1a;上篇博客中&#xff0c;我们为了使二叉搜索树不会出现”一边倒“的情况&#xff0c;使用了AVL树对搜索树进行了处理&#xff0c;从而解决了数据在有序或者接近有序时出现的情况。但是AVL树还会…

Apple 添加了 13 英寸 iPad Air

劈啪&#xff01;苹果推出的新款 iPad Air&#xff0c;将所有梦想变为现实&#xff01;它配备了强大的后置 12MP 摄像头和前置 12MP 摄像头&#xff0c;令您的拍摄体验更加出色。苹果还加入了 Apple Pencil 悬停功能&#xff0c;让您的创作更加灵活。 这款 iPad Air 不仅速度加…

武汉凯迪正大—电能质量测试仪功能特点

武汉凯迪正大电能质量测试仪功能特点 1. 仪器是专门用于检测电网中发生波形畸变、谐波含量、三相不平衡等电能质量问题的高精度测试仪器&#xff1b;同时还具备电参量测试、矢量分析的功能。 2. 可精确测量电压、电流、有功功率、无功功率、相角、功率因数、频率等多种电参量…

PowerBI实用技巧——案例十一 (根据所选日期动态滚动显示日期)

分享一波常用的日期动态滚动显示的小技巧,类似的方法还有很多&#xff0c;这里举3个小案例参考。 一、根据所选日期滚动显示近12月的数据&#xff08;日期为年月格式&#xff09; 效果图&#xff1a; 实现逻辑&#xff1a; rolloing_month //所选日期为年月格式,根据所选日…