Oracle技术之了解db file scattered read等待事件

Oracle在执行全表扫描(Full Table Scan,FTS)、全索引扫描(Index Full  Scan)或快速索引全扫描(Index Fast Full Scan)时,为保障性能,尽量一次性读取多个块,这称为Multi Block I/O。每次执行Multi Block I/O,都会等待物理I/O结束,此时等待db file scattered read事件。


但我见过不少朋友在研究db file scattered read等待的时候,总是说模拟不出这个等待事件出来。好,看下面环境:


sys@MAA> select * from v$version;


BANNER

----------------------------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

PL/SQL Release 11.2.0.3.0 - Production

CORE    11.2.0.3.0      Production

TNS for Linux: Version 11.2.0.3.0 - Production

NLSRTL Version 11.2.0.3.0 - Production


我用到的脚本:


[oracle@maa3 ~]$ cat showevent.sql

select event, total_waits, time_waited

from v$session_event

where sid=(select sid from v$mystat where rownum=1)

order by 3 desc

/


[oracle@maa3 ~]$ cat GetHparDes.sql

set pagesize 9999

set line 130

col NAME for a20

col VALUE for a20

col DESCRIB for a80

SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc DESCRIB

    FROM SYS.x$ksppi x, SYS.x$ksppcv y

WHERE x.inst_id = USERENV ('Instance')

    AND y.inst_id = USERENV ('Instance')

    AND x.indx = y.indx

    AND x.ksppinm LIKE '%&par%'

/  


我有一张100万记录的表,目前没有创建任何索引


luocs@MAA> select count(*) from LTB;


COUNT(*)

----------

  1000000


数据库采用AMM,memory_target分配了500M


sys@MAA> show parameter memory_target


NAME                                 TYPE                   VALUE

------------------------------------ ---------------------- ------------------------------

memory_target                        big integer            500M


我进行了一次FTS扫描,从10046 trace file里只能看到大量direct path read事件,而看不到期待的db file scattered read等待事件


……


WAIT #47878792991760: nam='direct path read' ela= 40 file number=8 first dba=131 block cnt=5 obj#=23315 tim=1356465468282010


WAIT #47878792991760: nam='direct path read' ela= 38 file number=8 first dba=200 block cnt=8 obj#=23315 tim=1356465468282079


WAIT #47878792991760: nam='direct path read' ela= 54 file number=8 first dba=217 block cnt=15 obj#=23315 tim=1356465468282367


……


Oracle 11g,在大表的全表扫描算法上有新的变化,根据表的大小、高速缓存的大小等信息,决定是否绕过SGA直接从磁盘读取数据。而10g则是全部通过高速缓存读取数据。Oracle 11g认为大表全表时使用直接路径读,可能比10g中的数据文件散列读(db file scattered reads)速度更快,效率更高,因此我们看到的大部分为direct path read等待事件。


Oracle 11g提供我们选择权,这个选择权可以通过隐含参数来控制,就是"_serial_direct_read",此参数默认值为auto


sys@MAA> @GetHparDes

Enter value for par: serial_direct_read

old   6:      AND x.ksppinm LIKE '%&par%'

new   6:      AND x.ksppinm LIKE '%serial_direct_read%'


NAME                 VALUE                DESCRIB

-------------------- -------------------- --------------------------------------------------------------------------------

_serial_direct_read  auto                 enable direct read in serial


该隐含参数是动态参数,我们可以通过alter system set方式修改


- _serial_direct_read = FALSE,禁用direct path read


- _serial_direct_read = TURE,重新启用direct path read


我们可以将其值设置为NEVER,来减少derect path read的等待

sys@MAA> alter system set "_serial_direct_read"=never;


System altered.


查看当前会话的SPID

luocs@MAA> select spid from v$process p, v$session s where p.addr=s.paddr and sid=(select sid from v$mystat where rownum=1);


SPID

------------------------------------------------

26601


通过10046事件查看

sys@MAA> oradebug setospid 26601

Oracle pid: 35, Unix process pid: 26601, image: [email protected] (TNS V1-V3)

sys@MAA> oradebug unlimit

Statement processed.

sys@MAA> oradebug event 10046 trace name context forever,level 12

Statement processed.


执行一个FTS

luocs@MAA> select count(*) from ltb;


COUNT(*)

----------

  1000000


sys@MAA> oradebug event 10046 trace name context off

Statement processed.

sys@MAA> oradebug tracefile_name

/u01/app/oracle/diag/rdbms/maa/maa/trace/maa_ora_26601.trc


这下我们能够看到大量db file scattered read了。

[oracle@maa3 ~]$ vi /u01/app/oracle/diag/rdbms/maa/maa/trace/maa_ora_26601.trc…….

…….

WAIT #47878792599648: nam='db file scattered read' ela= 34 file#=8 block#=131 blocks=5 obj#=23315 tim=1356470039698744

WAIT #47878792599648: nam='db file scattered read' ela= 27 file#=8 block#=200 blocks=8 obj#=23315 tim=1356470039699325

WAIT #47878792599648: nam='db file scattered read' ela= 20 file#=8 block#=217 blocks=7 obj#=23315 tim=1356470039699788

WAIT #47878792599648: nam='db file scattered read' ela= 22 file#=8 block#=224 blocks=8 obj#=23315 tim=1356470039700179

WAIT #47878792599648: nam='db file scattered read' ela= 19 file#=8 block#=241 blocks=7 obj#=23315 tim=1356470039700589

…….


event事件里也能看到其内容

luocs@MAA> @showevent


EVENT                                                             TOTAL_WAITS TIME_WAITED

----------------------------------------------------------------- ----------- -----------

SQL*Net message from client                                                24       21760

db file sequential read                                                   103          57

db file scattered read                                                    121          35

db file parallel read                                                       2           2

events in waitclass Other                                                   1           0

SQL*Net message to client                                                  25           0

Disk file operations I/O                                                    5           0

SQL*Net break/reset to client                                               1           0

KSV master wait                                                             2           0


9 rows selected.


下面我写一个PL/SQL来批量FTS,为效果明显,我定期刷新db cache

declare

       c integer;

begin

       for i in 1 .. 100 loop

               select count(*) into c from ltb;

               if mod(i,10)=0 then

                       execute immediate 'alter system flush buffer_cache';

               end if;

       end loop;

end;

/


在另一个会话通过v$session_wait观察:

sys@MAA> select SID, EVENT, P1, P2, P3 from V$SESSION_WAIT where event like '%scattered%';


SID EVENT                                                           P1         P2         P3

---------- ------------------------------------------------------- ---------- ---------- ----------

       37 db file scattered read                                           9        320         37


sys@MAA> select SID, EVENT, P1, P2, P3 from V$SESSION_WAIT where event like '%scattered%';


SID EVENT                                                           P1         P2         P3

---------- ------------------------------------------------------- ---------- ---------- ----------

       37 db file scattered read                                           9        898         37


sys@MAA> select SID, EVENT, P1, P2, P3 from V$SESSION_WAIT where event like '%scattered%';


SID EVENT                                                           P1         P2         P3

---------- ------------------------------------------------------- ---------- ---------- ----------

       37 db file scattered read                                          11       8293         27


sys@MAA> select SID, EVENT, P1, P2, P3 from V$SESSION_WAIT where event like '%scattered%';


SID EVENT                                                           P1         P2         P3

---------- ------------------------------------------------------- ---------- ---------- ----------

       37 db file scattered read                                          10        935         25


�C OK,轻易看到了db file scattered read等待事件。


下面开始看索引的情况,我添加一个唯一主键


luocs@MAA> alter table ltb add constraint cons_ltb_pk primary key(id);


Table altered.


现在查询会走IFFS

luocs@MAA> set autot trace exp

luocs@MAA> select count(id) from ltb;


Execution Plan

----------------------------------------------------------

Plan hash value: 903694340


-----------------------------------------------------------------------------

| Id  | Operation             | Name        | Rows  | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------

|   0 | SELECT STATEMENT      |             |     1 |   571   (1)| 00:00:07 |

|   1 |  SORT AGGREGATE       |             |     1 |            |          |

|   2 |   INDEX FAST FULL SCAN| CONS_LTB_PK |  1000K|   571   (1)| 00:00:07 |

-----------------------------------------------------------------------------


通过下面的PL/SQL,可以观察v$session_wait的事件

declare

       c integer;

begin

       for i in 1 .. 100 loop

               select count(*) into c from ltb;

               if mod(i,10)=0 then

                       execute immediate 'alter system flush buffer_cache';

               end if;

       end loop;

end;

/


sys@MAA> select SID, EVENT, P1, P2, P3 from V$SESSION_WAIT where event like '%scattered%';


SID EVENT                                                           P1         P2         P3

---------- ------------------------------------------------------- ---------- ---------- ----------

       37 db file scattered read                                          11       8524         10


sys@MAA> select SID, EVENT, P1, P2, P3 from V$SESSION_WAIT where event like '%scattered%';


SID EVENT                                                           P1         P2         P3

---------- ------------------------------------------------------- ---------- ---------- ----------

       37 db file scattered read                                           9       1026         37


sys@MAA> select SID, EVENT, P1, P2, P3 from V$SESSION_WAIT where event like '%scattered%';


SID EVENT                                                           P1         P2         P3

---------- ------------------------------------------------------- ---------- ---------- ----------

       37 db file scattered read                                          11       8524         10


下面通过10046事件查看

trace内容里找到等待事件:

…...

WAIT #47752647311696: nam='db file sequential read' ela= 28 file#=8 block#=170 blocks=1 obj#=23883 tim=1356481191781943

WAIT #47752647311696: nam='db file scattered read' ela= 26 file#=8 block#=171 blocks=5 obj#=23883 tim=1356481191782086

WAIT #47752647311696: nam='db file scattered read' ela= 2733 file#=9 block#=144 blocks=8 obj#=23883 tim=1356481191785276

WAIT #47752647311696: nam='db file scattered read' ela= 2479 file#=10 block#=137 blocks=7 obj#=23883 tim=1356481191788466

WAIT #47752647311696: nam='db file scattered read' ela= 2544 file#=11 block#=8760 blocks=8 obj#=23883 tim=1356481191791597

WAIT #47752647311696: nam='db file scattered read' ela= 31 file#=8 block#=209 blocks=7 obj#=23883 tim=1356481191792242

…...


db file scattered read等待事件一般属于"正常"等待事件,所以除非特殊情况,我们不需要太过在意。


若果列出db file scattered read等待的解决方法,那就如下:


从应用程考虑,需要帅选出主要发生db file scattered read等待的SQL语句,减少不必要的执行FTS或Index Full Scan,务必按照业务需求来修改,不能盲目说哪种效率必须好,要知道读取大量数据时,多数情况下FTS性能更优。

从Oracle内存层考虑,可以使用多重缓冲池,或者提高DB_FILE_MULTIBLOCK_READ_COUNT参数值。

从Oracle段层考虑,使用合理的分区方案

从OS层考虑,提高物理I/O性能


oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html


你可能感兴趣的:(oracle,DB,DB,File,File,read,scattered,scattered,read等待事件)