cpu占用过高怎么办 cpu占用过高怎么办( 四 )


,qp.query_planAS"Query Plan"
FROMsys.dm_exec_query_statsqs
CROSSAPPLYsys.dm_exec_sql_text(qs.plan_handle)st
CROSSAPPLYsys.dm_exec_query_plan(qs.plan_handle)qp
ORDER BYtotal_elapsed_time/execution_countDESC
我们把建索引前后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)
CREATE NONCLUSTERED INDEX IX_eventlog_moid ON dbo.eventlog(MgrObjId)
但是无论我怎么试,都是没有利用到索引,难道IN子句和NOT IN子句是没法利用索引一定会引起表扫描 。于是上网查资料,找到桦仔的文章,这里面有解答:
SQLSERVER对筛选条件(search argument/SARG)的写法有一定的建议
SQLSERVER对筛选条件(search argument/SARG)的写法有一定的建议
对于不使用SARG运算符的表达式,索引是没有用的,SQLSERVER对它们很难使用比较优化的做法 。非SARG运算符包括
NOT、、NOT EXISTS、NOT IN、NOT LIKE和内部函数,例如:Convert、Upper等
对于不使用SARG运算符的表达式,索引是没有用的,SQLSERVER对它们很难使用比较优化的做法 。非SARG运算符包括
NOT、、NOT EXISTS、NOT IN、NOT LIKE和内部函数,例如:Convert、Upper等
但是这恰恰说明了IN是可以建立索引的啊 。百思不得其解,经过一番的咨询之后,得到了解答:
不一定是利用索引就是好的,sqlserver根据你的查询的字段的重复值的占比,决定是表扫描还是索引扫描
不一定是利用索引就是好的,sqlserver根据你的查询的字段的重复值的占比,决定是表扫描还是索引扫描
有道理,但是我查看了下,重复值并不高,怎么会有问题呢 。
关键是,你select的字段,这个地方使用索引那么性能更差,你select字段 id,addrid,agentbm,mgrobjtypeid,name都不在索引里 。
关键是,你select的字段,这个地方使用索引那么性能更差,你select字段 id,addrid,agentbm,mgrobjtypeid,name都不在索引里 。
真是一语惊醒梦中人,缺的是包含索引!!!关于包含索引的重要性我在这篇文章《我是如何在SQLServer中处理每天四亿三千万记录的》已经提到过了,没想到在这里又重新栽了个跟头 。实践,真的是太重要了!
通过建立包含索引来让SQL语句走索引
好吧,立马建立相关索引:
IF NOT EXISTS(SELECT*FROMsysindexesWHEREid=OBJECT_ID('eventlog')ANDname='IX_eventlog_moid')
CREATENONCLUSTEREDINDEXIX_eventlog_moidONdbo.eventlog(MgrObjId)INCLUDE(EventBm,AgentBM)
IF NOT EXISTS(SELECT*FROMsysindexesWHEREid=OBJECT_ID('eventlog')ANDname='IX_eventlog_moid')
CREATENONCLUSTEREDINDEXIX_eventlog_moidONdbo.eventlog(MgrObjId)INCLUDE(EventBm,AgentBM)
我们再来看看查询计划:
看到没有,已经没有eventlog表的表扫描了 。我们再来比较前后的CPU:
很明显,这个count的优化,对查询top的语句依然的生效的 。目前为止,这两个查询用上去之后,再也没有CPU过高的现象了 。
其他优化手段
通过服务端的推送,有事件告警或者解除过来才查询数据库 。
优化上述查询语句,比如count(*)可以用count(0)替代
优化语句,先查询出所有的MgrObjId,然后在做连接
为管理对象、地点表等增加索引
添加了索引之后,事件表的插入就会慢,能够再怎么优化呢?可以分区建立索引,每天不忙的时候,把新的记录移入到建好索引的分区