ORACLEl数据库log group不足及dbwn进程太少导致加载数据很慢问题
在使用外部表及imp向ORACLE数据库加载数据的时候,发现加载速度特别慢,加载一张1G多的数据需要2个小时,加载7G多的数据需要将近一下午的时间,经过分析发现大量等待都是log file switch和log buffer space等待事件。
SQL> select sql_id,OSUSER,MACHINE,TERMINAL,PROGRAM,EVENT,STATE from v$session where username='CHGSHS'; PROGRAM EVENT STATE ----------------------------------- ---------------------------------------- ---------- sqlplus@SL010A-ISITDB3 (TNS V1-V3) log file switch (checkpoint incomplete) WAITING / PROGRAM EVENT STATE ----------------------------------- ---------------------------------------- ---------- sqlplus@SL010A-ISITDB3 (TNS V1-V3) log buffer space WAITING
检查发现当前数据库有4组redo日志,每个redo文件500M,而且除CURRENT日志组外,其他日志组均是ACTIVE状态。
GROUP# SEQUENCE# BYTES MEMBERS ARC STATUS ---------- ---------- ---------- ---------- --- ------- 1 1075 524288000 1 NO ACTIVE 2 1076 524288000 1 NO ACTIVE 3 1077 524288000 1 NO ACTIVE 4 1078 524288000 1 NO CURRENT
日志切换要等到日志状态为INACTIVE状态才可以,这就需要等内存中的数据写入到数据文件中,可见目前磁盘写入速度不足,导致内存中的数据无法及时写入到磁盘,经查看,当前数据库只有3个数据写进程(dbwn)。
SQL> show parameter db_w NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_writer_processes integer 3
针对这种情况,最有效的方法是增大数据写进程的个数,但是调整数据写进程需要重启数据库才能生效,如果数据库不能及时重启,可以增加日志组来缓解这个问题,我这里增加了6组1GB的日志,增加后非常快新增的日志就被用到了,而且也全都是ACTIVE状态,也就是为解决这个问题,10个日志组还不够。
GROUP# THREAD# SEQUENCE# BYTES BLOCKSIZE MEMBERS ARC STATUS ---------- ---------- ---------- ---------- ---------- ---------- --- ------- 1 1 1015 524288000 512 1 NO ACTIVE 2 1 1016 524288000 512 1 NO ACTIVE 3 1 1017 524288000 512 1 NO ACTIVE 4 1 1018 524288000 512 1 NO ACTIVE 5 1 1009 1073741824 512 1 NO CURRENT 6 1 1008 1073741824 512 1 NO ACTIVE 7 1 1009 1073741824 512 1 NO ACTIVE 8 1 1010 1073741824 512 1 NO ACTIVE 9 1 1013 1073741824 512 1 NO ACTIVE 10 1 1014 1073741824 512 1 NO ACTIVE 10 rows selected.
虽然增加日志组没有起到根本问题,但是数据加载速度明显加快,虽然也很难接受。最终的解决方法还是调整数据写进程。
SQL> alter system set db_writer_processes=10 scope=spfile; System altered.
这里将数据写进程调整为10个,之前的3个是默认值,这个默认值是根据CPU的核数计算出来的,默认是CPU核数除以8,当前的数据服务器是24核,所以默认值就是3。
SQL> show parameter cpu NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ cpu_count integer 24 parallel_threads_per_cpu integer 2 resource_manager_cpu_allocation integer 24
这里因为要加快数据加载的速度设置为10个数据写进程,数据写进程并不是越多越好,设置的多了,占用的CPU资源也就越多,生产环境需要根据相关的需求进行设置,一般来讲,生产环境服务器的CPU都比较多,默认值基本也够用了,比如40核的3850服务器,默认数据写进程就是5个,如果不是BI系统,基本够用了。
调整完数据写进程,在闲时重启数据库,再次加载数据速度明显提升,通过外部表的方式加载30G的数据,开8个并行,10分钟以内即可完成,之前可能需要一天一宿,而且在数据加载时,在也没有遇到日志等待的问题。
GROUP# THREAD# SEQUENCE# BYTES BLOCKSIZE MEMBERS ARC STATUS ---------- ---------- ---------- ---------- ---------- ---------- --- -------- 1 1 1075 1073741824 512 1 NO ACTIVE 2 1 1076 1073741824 512 1 NO ACTIVE 3 1 1077 1073741824 512 1 NO ACTIVE 4 1 1078 1073741824 512 1 NO ACTIVE 5 1 1079 1073741824 512 1 NO CURRENT 6 1 1068 1073741824 512 1 NO INACTIVE 7 1 1069 1073741824 512 1 NO INACTIVE 8 1 1070 1073741824 512 1 NO INACTIVE 9 1 1073 1073741824 512 1 NO INACTIVE 10 1 1074 1073741824 512 1 NO INACTIVE 10 rows selected.
重启数据库后,将之前的4组500M的日志组也调整到了1GB。
这个优化,最终的解决方法就是增加了数据写进程(dbwn,也有人叫dbwr)的个数,使内存中的数据可以快速写入到磁盘,加快了检查点的完成时间,减少了日志等待的问题,可见优化效果非常明显。