一次sqlldr导入慢的解决过程

今天在客户处进行培训时,客户抱怨到,sqlldr的速度太慢,说是从昨天晚上加载数据到今天上午,都没有结束。加载的文本文件大小为10M,大概包含10万条记录。按照我的理解,sqlldr几乎不可能花这么长的时间的。

于是,让客户查询v$session_wait,发现执行sqlldr加载的session(session id为33)正在等待library cache lock的等待事件。很明显,sqlldr一直在等待,而不是在进行实际的加载工作。

既然是等待library cache lock,说明有其他的进程锁定了要加载的表,导致sqlldr
无法获得该表上的lock。这属于shared pool里的一种争用。

然后,我让客户发出下面的SQL
 select /*+ ordered */
    w1.sid waiting_session,
    h1.sid holding_session,
    w.kgllktype lock_or_pin,
    w.kgllkhdl address,
    decode(h.kgllkmod,0,'None',1,'Null',2,'Share',3,'Exclusive','Unknown') mode_held,
    decode(w.kgllkreq,0,'None',1,'Null',2,'Share',3,'Exclusive','Unknown') mode_requested
    from dba_kgllock w, dba_kgllock h, v$session w1, v$session h1
    where (((h.kgllkmod != 0) and (h.kgllkmod != 1)
     and ((h.kgllkreq = 0) or (h.kgllkreq = 1)))
     and (((w.kgllkmod = 0) or (w.kgllkmod = 1))
     and ((w.kgllkreq != 0) and (w.kgllkreq != 1))))
     and w.kgllktype = h.kgllktype
     and w.kgllkhdl = h.kgllkhdl
     and w.kgllkuse = w1.saddr
     and h.kgllkuse = h1.saddr;

该sql可以很清楚的显示出,谁阻碍了谁。查询结果显示23号session锁定了33号session。于是发出下面的sql:
select sql_text from v$sql
where hash_value=(select sql_hash_value from v$session where sid=23);

可以看到23号session在干什么。结果发现它在执行重新rebuild索引的命令:
alter index XXX rebuild online;

而该索引正是要加载的表上的索引,于是可以肯定,该语句阻塞了sqlldr的操作。
于是在确定了23号session无关紧要以后,将该session直接切断即可。切断该session以后,sqlldr很快就完成了加载数据的工作。

结论:
当发现oracle里某个动作特别慢的时候,先查看一下它在等待什么。

可能并不一定是这个动作本身慢,而是其他的原因导致它无法进行下去。



这个问题正是我们公司高度关注的问题,目前各省入库在高峰期,堆积较严重。

个人思考方向:

1.sga导致

2.log file,redo大小

3.直接路径加载

4.避开应用高峰(查看job和wait)

明天去公司分析,希望有点线索......

你可能感兴趣的:(sql,工作,cache,session,null,library)