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,然后在做连接  
为管理对象、地点表等增加索引  
添加了索引之后,事件表的插入就会慢,能够再怎么优化呢?可以分区建立索引,每天不忙的时候,把新的记录移入到建好索引的分区


特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。