oracle cpu使用率接近100%排查思路

一  问题现象

linux 服务器cpu使用率接近100%


使用vmstat 1 10查看id项接近1


top查看有好几个oracle进程排在前面

 

使用如下语句查看使用cpu高的sql

占用cpu总时间排序

select * from (select s.sid,s.serial#,s.username,s.program,t.sql_id,t.cpu_time/1000000 as sum_cpu_time_seconds,t.executions,t.sql_text

from v$session s,v$sql_text where s.sql_id=t.sql_id and s.status='ACTIVE' order by sum_cpu_time_seconds desc) where rownum<=10



平均cpu执行时间前10条sql

select * from (select s.sid,s.serial#,s.username,s.program,t.sql_id,t.cpu_time/1000000/t.executions as per_cpu_time_seconds,t.executions,t.sql_text

from v$session s,v$sql_text where s.sql_id=t.sql_id and s.status='ACTIVE' order by per_cpu_time_second desc) where rownum<=10


发现很多sid,serial$指向通一个sql,反复执行上面查询,executions增长很快,sum_cpu_time_seconds也增长很快



确认top中的pid对应的(sid,serial#)

select p.spid,s.sid,s.serial#,s.username,s.osuer from v$session s,v$process p

where s.paddr=p.add and p.spid in ('','','') ;



查看sql执行计划

select * from table(dbms_xplan.display_cursor('&SQL_ID',&child_number));

select * from table(dbms_xplan.display_awr('******'));


查看表的统计信息

  select t.OWNER, t.TABLE_NAME, t.NUM_ROWS, t.LAST_ANALYZED, t.PARTITIONED

  from dba_tables t where t.TABLE_NAME in ('a','b', 'c')


如果上次收集统计信息时间在1周以前,或者num_rows和当前表中记录数差距较大,应对该表新收集统计信息:

  

  索引的统计信息

  select owner,table_name,index_name,last_analyzed from dba_indexes where table_name ='&table_name';

     

表记录数

     select count(PK) from TAB;

   表的属性/是否为分区表:


收集表的统计信息


exec dbms_stats.gather_table_stats(ownname=>'ht2',tabname=>'ht_DEPT',estimate_percent=>100,method_opt=>'for all columns size repeat',no_invalidate=>false,degree=>8,cascade=>true);
exec dbms_stats.gather_table_stats(ownname=>'ht',tabname=>'ht_tab_fy',estimate_percent=>100,method_opt=>'for all columns size repeat',no_invalidate=>false,degree=>8,cascade=>true);

查看表上的索引信息


1  确认该表上的索引状态正常:

SELECT OWNER,INDEX_NAME

      FROM   dba_indexes 

      WHERE  status<>'VALID'

      AND    partitioned <> 'YES'

      UNION ALL

SELECT INDEX_OWNER,INDEX_NAME

      FROM   dba_ind_partitions 

      WHERE  status<>'USABLE'

      UNION ALL

SELECT INDEX_OWNER,INDEX_NAME

      FROM   dba_ind_subpartitions 

      WHERE  status<>'USABLE'

不应该返回记录,或返回索引和查询表无关



 确认表上有合适的索引可以被利用:

sysdba用户执行:

set lines 132

col column_name for a40

col index_name for a30

select index_name,column_name,COLUMN_POSITION , INDEX_OWNER

from dba_ind_columns where table_name ='&table_name'

order by 1,3 asc;


select index_name,index_type,table_name,uniqueness,status,num_rows from dba_indexes where owner='SCOTT'  and table_name='EMP1'



根据sql_id查看历史执行计划

SELECT sql_id,plan_hash_value,

SUM(elapsed_time_total)/SUM(executions_total)/1000000 avg_elapsedt_secs

FROM dba_hist_sqlstat

WHERE sql_id = 'brk7h8vn51wm2'

GROUP BY sql_id,plan_hash_value ;



数据分布情况:

set line 120

col OWNER for a10

col COLUMN_NAME for a18

select OWNER,TABLE_NAME,COLUMN_NAME,NUM_DISTINCT,NUM_NULLS  from dba_tab_columns where TABLE_NAME='&table_name';


NUM_DISTINCT任意列不同值的数量


dba_tables 的num_rows可以得到某个表的行数

   列的可选择性分析:


SELECT COUNT(*) from BRAS.TJ_ZJJY_5;

SELECT COUNT(distinct entry_id) from BRAS.TJ_ZJJY_5;

SELECT COUNT(distinct ishandle) from BRAS.TJ_ZJJY_5;

SELECT COUNT(distinct bankcode) from BRAS.TJ_ZJJY_5;



--索引定义语句

set pagesize 0

set long 90000

set feedback off

set echo off

select dbms_metadata.get_ddl('INDEX','PK_LD_CAR_MONITOR','LOGISTICS') from dual;


索引建立原则:

主要索引:一般索引,唯一性索引,组合索引,

         组合索引:应用最广泛,使用时候选择性最高(唯一值)放在最前面

         建立索引考虑事项:结果集,数据量很大,但结果集很小

         检查where查询中限定性比较强的条件

表连接方式:hash连接(数据量大的表之间)

           NL  (循环遍历),适合结果集很小,在第一个表中查询的结果少

---在dept1上创建unique索引

create unique index pk_dept1_index on dept1(deptno);


删除索引

drop index EMP_EMPNO_IDX;


---索引创建示例:

在表TJ10,TJ30.T100 组合索引 

         create index TJ_ZJJY_ZH_INX_1 on TJ10(entry_id, ishandle, bankcode);

          create index TJ_ZJJY_ZH_INX_2 on TJ30(entry_id, ishandle, bankcode);

          create index TJ_ZJJY_ZH_INX_3 on TJ100(entry_id, ishandle, bankcode);

          create index TJ_ZJJY_ZH_INX_4 on TJ1102(entry_id, ishandle, bankcode);



create index  ET_BU_IDX on ET_BUSIFORM_TB(NODE_NO,FORM_TYPE,ACTIVE_FLAG,1) invisible;

count(*) 需要计算总行,索引不记录空行,需要一定的技巧

show parameter invisible 确定参数为false

create index  ET_BU_IDX on ET_BUSIFORM_TB(NODE_NO,FORM_TYPE,ACTIVE_FLAG,1) invisible;


(可以建立node_no,from_type,active_flag,1)这样的索引

create index on (node_no,from_type,active_flag,1)


确定需要建立索引的列


1 主键约束,除开主键列的其他列的唯一性约束,都会创建一个索引

2 外键需要手工建立索引

3 适合创建索引的列

   where后的列,组合索引,select子句中的列,group by,order by union distinct子句中使用的列



注:优化器忽略索引的原因:

    使用不等条件 <> 

    使用通配符 ‘%lapti’,而使用通配符apti%可以走index range scan

    空值:唯一索引的所有列都是null值,这些列不会包含在索引中,即使有唯一索引

   查询中包含函数

   



请使用浏览器的分享功能分享到微信等