一次9i数据库优化
昨天帮客户优化一套9.2.0.4的数据库,业务高峰期,客户的数据库服务器CPU负载几乎100%,用户已经无法登录业务系统,SQL执行时间超长。客户的服务器48核CPU,内存32G。
经过现场分析, 发现3处对性能影响较大的地方。首先是内存设置不当,该部分对服务器压力造成较大影响。
SELECT COUNT (*) AS col_0_0_ FROM PRESSO.BIZ_PRESSCARD_LOGOUT presscardl0_, PRESSO.BIZ_REPORTER_INFO reporterin1_ WHERE presscardl0_.CARD_UUID = reporterin1_.CARD_UUID AND 1 = 1 AND presscardl0_.APPLY_STATUS = 2 AND presscardl0_.NEXT_ORGID = '1' AND reporterin1_.STATE = '7';
在问题时段,该SQL运行需要1分多的时间,而这两张表数据量均不大,以下是该SQL的执行计划和统计信息。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=20 Card=1 Bytes=69)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'BIZ_PRESSCARD_LOGOUT'
(Cost=10 Card=1 Bytes=50)
3 2 NESTED LOOPS (Cost=4 Card=1 Bytes=69)
4 3 TABLE ACCESS (BY INDEX ROWID) OF 'BIZ_REPORTER_INFO'
(Cost=10 Card=1 Bytes=19)
5 4 INDEX (RANGE SCAN) OF 'STATE_REPORTER_INFO_INDEX'
(NON-UNIQUE) (Cost=4 Card=1)
6 3 INDEX (RANGE SCAN) OF 'INDEX_LOGOUT_CARD_UUID' (NON-
UNIQUE) (Cost=4 Card=1)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
796225 consistent gets
5245 physical reads
0 redo size
490 bytes sent via SQL*Net to client
655 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed再次运行这个SQL,发现执行时间和统计信息部分基本没变。
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
796225 consistent gets
5087 physical reads
0 redo size
490 bytes sent via SQL*Net to client
655 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed为什么刚刚运行完的SQL,再次运行还需要这么多的物理读?这是个问题,经过分析发现,db_cache_size设置的不合理。
SQL > SHOW PARAMETER DB_CACHE_SIZE NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_cache_size big integer 33792
可见,db_cache_size只有30多M,存不下需要处理的数据,下次再执行SQL,就需要物理读,这样就造成了大量的CPU等待,经查看,该数据库SGA_MAX_SIZE被其他DBA设置为16G,shared_pool_size被设置为1G,讲shared_pool_size调整为2G,db_cache_size调整为12G,性能有所提升,多次运行后,该SQL运行需要将近3秒,逻辑读下降一半,物理读为0.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=1 Bytes=69)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'BIZ_PRESSCARD_LOGOUT'
(Cost=2 Card=1 Bytes=50)
3 2 NESTED LOOPS (Cost=4 Card=1 Bytes=69)
4 3 TABLE ACCESS (BY INDEX ROWID) OF 'BIZ_REPORTER_INFO'
(Cost=2 Card=1 Bytes=19)
5 4 INDEX (RANGE SCAN) OF 'STATE_REPORTER_INFO_INDEX'
(NON-UNIQUE) (Cost=1 Card=1)
6 3 INDEX (RANGE SCAN) OF 'INDEX_LOGOUT_CARD_UUID' (NON-
UNIQUE) (Cost=1 Card=1)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
497641 consistent gets
0 physical reads
0 redo size
490 bytes sent via SQL*Net to client
655 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed查看表和索引的统计信息,发现统计信息都是一年前收集的,重新对表和所以进行分析后,SQL执行10毫秒即可查询出结果,逻辑读大大降低。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=5 Card=1 Bytes=67)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'BIZ_REPORTER_INFO' (Co
st=3 Card=1 Bytes=17)
3 2 NESTED LOOPS (Cost=5 Card=1 Bytes=67)
4 3 TABLE ACCESS (FULL) OF 'BIZ_PRESSCARD_LOGOUT' (Cost=
2 Card=1 Bytes=50)
5 3 INDEX (RANGE SCAN) OF 'CARD_UUID_INDEX' (NON-UNIQUE)
(Cost=2 Card=1)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2862 consistent gets
0 physical reads
52 redo size
490 bytes sent via SQL*Net to client
655 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed对业务用户所有表和索引进行分析,此时业务系统基本恢复正常,高峰期CPU使用基本在1%-3%直接,偶尔会到9%,但很快就会降下去。
客户反馈在批量审批100条信息的时候,之前需要5分钟才能审批完,现在虽然有所提升(3分钟),但是还比较慢。经和开发人员交流,发现审批更新的表都存在触发器,将更新的信息同步到另一个用户的表里面,经查询,另一个用户基本没有索引。按照触发器的SQL,创建索引后,只需20秒即可审批完,如再需优化,就需要修改业务逻辑了,客户表示可以接受了。
下面摘录业务人员统计的优化对比信息。
| 对比项 | 优化前 | 优化后 |
| 时间段 | 2014-08-20 14:00 – 17:30 | 2014-08-2114:00 – 16:46 |
| 同时在线人数 | ~160 | ~170 |
| CPU 总体资源占用 | 60% — 80% | 1.5% — 10% |
| CPU load average活跃进程数 | 25 – 27 | 1.21 – 3.9 |
| 高峰时每小时完成审批业务数 | ~4500条(14:00 – 15:00) | ~16000 条(14:00 – 15:00) |
| 累计完成审批业务数 | 19745 | |
| 单用户一次审批100条耗时 | 3-5分钟 | 20– 30秒 |
| 登录、录入等功能 | 基本不可用 | 稳定可用 |