11g direct path read 和 10046 10949 event

11g 相比较10G出现了很多的新功能,其中很多还是很有用的。但是新的事物刚出来,就是不太稳定,虽然到现在11G已经是11.2.0.3

其中一个就是Oracle 11g has implemented direct path read for the serial full table scan,摘录自《Disabling direct path read for the serial full table scan 11g》,http://afatkulin.blogspot.com/2009/01/11g-adaptive-direct-path-reads-what-is.html 等:
There have been changes in 11g in the heuristics to choose between direct path reads or reads through buffer cache for serial table scans.In 10g, serial table scans for “large” tables used to go through cache (by default) which is not the case anymore.  In 11g, this decision to read via direct path or through cache is based on the size of the table, buffer cache size and various other stats.

When direct path reads starts to happen?

It is known that somewhat reliable figure is your _small_table_threshold multiplied by 5 (mentioned by Tanel Poder on oracle-l recently). You can discover it using quick and dirty test case similar to this:

 

关于 5 * _small_table_threshold 这一点我没有验证过,但是是有这么一个值的存在:

 

1 先确定版本和small_table_threshold的大小

SQL> select * from v$version;

 

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 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@RHEL55_node1 ~]$

_small_table_threshold        119     lower threshold level of table size for direct reads

 

2  “small table” test

SQL> create table t1(c1 number, c2 char(2000), c3 char(2000), c4 char(2000)) tablespace data01;

 

Table created.

 

SQL> insert into t1 

  2    select level, 'x', 'x', 'x'

  3   from dual connect by level <= 10 + 2*&sth;

Enter value for sth: 20

old   3:  from dual connect by level <= 10 + 2*&sth

new   3:  from dual connect by level <= 10 + 2*20

 

50 rows created.

 

SQL> commit;

 

Commit complete.

 

SQL>  alter system flush buffer_cache;

 

SQL> set linesize 300

SQL> select vm.sid, vs.name, vm.value                           

  2    from v$mystat vm, v$sysstat vs                          

  3    where vm.statistic# = vs.statistic#                     

  4     and vs.name in ('cleanouts only - consistent read gets',

  5                      'session logical reads',              

  6                      'physical reads',                     

  7                      'physical reads direct','redo size'); 

 

       SID NAME                                                                  VALUE

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

         1 session logical reads                                                     3

         1 physical reads                                                            2

         1 physical reads direct                                                     0

         1 redo size                                                                 0

         1 cleanouts only - consistent read gets                                     0

 

SQL> alter session set events '10046 trace name context forever, level 8';

 

Session altered.

 

SQL> select count(*) from t1;

 

  COUNT(*)

----------

        50

 

SQL> alter session set events '10046 trace name context off';

 

Session altered.

 

SQL> select vm.sid, vs.name, vm.value                          

  2    from v$mystat vm, v$sysstat vs                          

  3    where vm.statistic# = vs.statistic#                     

  4     and vs.name in ('cleanouts only - consistent read gets',

  5                      'session logical reads',              

  6                      'physical reads',                     

  7                      'physical reads direct','redo size'); 

 

       SID NAME                                                                  VALUE

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

         1 session logical reads                                                    55

         1 physical reads                                                           53

         1 physical reads direct                                                     0

         1 redo size                                                                 0

         1 cleanouts only - consistent read gets                                     0

 

select count(*)

from

 t1

 

 

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.03       0.07         51         52          0           1

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

total        4      0.03       0.07         51         52          0           1

 

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: SYS

Number of plan statistics captured: 1

 

Rows (1st) Rows (avg) Rows (max)  Row Source Operation

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

         1          1          1  SORT AGGREGATE (cr=52 pr=51 pw=0 time=71573 us)

        50         50         50   TABLE ACCESS FULL T1 (cr=52 pr=51 pw=0 time=60736 us cost=15 size=0 card=50)

 

 

Elapsed times include waiting on following events:

  Event waited on                             Times   Max. Wait  Total Waited

  ----------------------------------------   Waited  ----------  ------------

  SQL*Net message to client                       2        0.00          0.00

  Disk file operations I/O                        1        0.00          0.00

  db file sequential read                         4        0.00          0.00

  db file scattered read                         17        0.00          0.00

  SQL*Net message from client                     2        8.14          8.15

 

big table” test

SQL> set linesize 300

SQL>  select vm.sid, vs.name, vm.value

  2     from v$mystat vm, v$sysstat vs

  3     where vm.statistic# = vs.statistic#

  4      and vs.name in ('cleanouts only - consistent read gets',

  5                       'session logical reads',

  6                       'physical reads',

  7                       'physical reads direct','redo size');

 

       SID NAME                                                              VALUE

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

        26 session logical reads                                                46

        26 physical reads                                                       11

        26 physical reads direct                                                 0

        26 redo size                                                             0

        26 cleanouts only - consistent read gets                                 0

 

SQL> select count(*) from t1;

 

  COUNT(*)

----------

       605

 

SQL> select vm.sid, vs.name, vm.value

  2    from v$mystat vm, v$sysstat vs

  3    where vm.statistic# = vs.statistic#

  4     and vs.name in ('cleanouts only - consistent read gets',

  5                      'session logical reads',

  6                      'physical reads',

  7                      'physical reads direct','redo size');

 

       SID NAME                                                              VALUE

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

        26 session logical reads                                               773

        26 physical reads                                                      790

        26 physical reads direct                                               622

        26 redo size                                                             0

        26 cleanouts only - consistent read gets                                 0

 

select count(*)

from

 t1

 

 

call     count       cpu    elapsed       disk      query    current        rows

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

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.16       0.85        632        637          1           1

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

total        4      0.16       0.85        632        637          1           1

 

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: SYS

Number of plan statistics captured: 1

 

Rows (1st) Rows (avg) Rows (max)  Row Source Operation

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

         1          1          1  SORT AGGREGATE (cr=637 pr=632 pw=0 time=851875 us)

       605        605        605   TABLE ACCESS FULL T1 (cr=637 pr=632 pw=0 time=2631762 us cost=171 size=0 card=671)

 

 

Elapsed times include waiting on following events:

  Event waited on                             Times   Max. Wait  Total Waited

  ----------------------------------------   Waited  ----------  ------------

  SQL*Net message to client                       2        0.00          0.00

  Disk file operations I/O                        1        0.00          0.00

  db file sequential read                         3        0.04          0.05

  db file parallel read                           1        0.01          0.01

  direct path read                              315        0.45          0.61

  SQL*Net message from client                     2        4.65          4.65

 

4 对于10046 trace query

physical reads direct是包含在session logical reads里面的。 即,逻辑读的统计信息包含物理读的统计信息,这个也是我一开始挺疑惑的地方:

下面这个是工具tkprof输出的,我们绝大部分人都是理解为通过buffer get在一致性检索方式获得块时,执行逻辑I/O次数;

********************************************************************************

count    = number of times OCI procedure was executed

cpu      = cpu time in seconds executing

elapsed  = elapsed time in seconds executing

disk     = number of physical reads of buffers from disk

query    = number of buffers gotten for consistent read

current  = number of buffers gotten in current mode (usually for update)

rows     = number of rows processed by the fetch or execute call

********************************************************************************

其实这个从trace文件里可以看出绝大部分都是direct path read

 

PARSING IN CURSOR #10742416 len=23 dep=0 uid=0 ct=3 lid=0 tim=1331353130977474 hv=4235652837 ad='265585c8' sqlid='5bc0v4my7dvr5'

select count(*) from t1

END OF STMT

PARSE #10742416:c=0,e=1601,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=3724264953,tim=1331353130977453

EXEC #10742416:c=0,e=1456,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=3724264953,tim=1331353130979196

WAIT #10742416: nam='SQL*Net message to client' ela= 29 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=1331353130979564

WAIT #10742416: nam='Disk file operations I/O' ela= 1360 FileOperation=2 fileno=5 filetype=2 obj#=13562 tim=1331353130984136

WAIT #10742416: nam='db file sequential read' ela= 360 file#=5 block#=266 blocks=1 obj#=13562 tim=1331353130987120

WAIT #10742416: nam='db file sequential read' ela= 41206 file#=5 block#=1024 blocks=1 obj#=13562 tim=1331353131154473

WAIT #10742416: nam='db file sequential read' ela= 12111 file#=5 block#=265 blocks=1 obj#=13562 tim=1331353131166898

WAIT #10742416: nam='db file parallel read' ela= 19615 files=1 blocks=7 requests=7 obj#=13562 tim=1331353131187899

WAIT #10742416: nam='direct path read' ela= 827 file number=5 first dba=267 block cnt=1 obj#=13562 tim=1331353131190685

WAIT #10742416: nam='direct path read' ela= 349 file number=5 first dba=268 block cnt=2 obj#=13562 tim=1331353131191225

.........................省去几百行.....................................................................................

WAIT #10742416: nam='direct path read' ela= 369 file number=5 first dba=1532 block cnt=2 obj#=13562 tim=1331353131829358

WAIT #10742416: nam='direct path read' ela= 76 file number=5 first dba=1534 block cnt=2 obj#=13562 tim=1331353131829539

FETCH #10742416:c=168010,e=851525,p=632,cr=637,cu=1,mis=0,r=1,dep=0,og=1,plh=3724264953,tim=1331353131831374

STAT #10742416 id=1 cnt=1 pid=0 pos=1 bj=0 p='SORT AGGREGATE (cr=637 pr=632 pw=0 time=851875 us)'

STAT #10742416 id=2 cnt=605 pid=1 pos=1 bj=13562 p='TABLE ACCESS FULL T1 (cr=637 pr=632 pw=0 time=2631762 us cost=171 size=0 card=671)'

WAIT #10742416: nam='SQL*Net message from client' ela= 2629 driver id=1650815232 #bytes=1 p3=0 obj#=13562 tim=1331353131836316

FETCH #10742416:c=0,e=23,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,plh=3724264953,tim=1331353131836483

WAIT #10742416: nam='SQL*Net message to client' ela= 17 driver id=1650815232 #bytes=1 p3=0 obj#=13562 tim=1331353131836638

 

*** 2012-03-10 12:18:56.488

WAIT #10742416: nam='SQL*Net message from client' ela= 4650605 driver id=1650815232 #bytes=1 p3=0 obj#=13562 tim=1331353136488110

CLOSE #10742416:c=0,e=38,dep=0,type=0,tim=1331353136488429

 

5 ORACLE在读一张表之间如何能预知表的大小

这个是可以计算出来的,也就是统计信息:

 

SQL> exec dbms_stats.gather_table_stats(user, 'T1',no_invalidate=>false);

PL/SQL procedure successfully completed.

 

SQL> exec show_space('T1','auto','T','Y');

Total Blocks............................640

Total Bytes.............................5242880

Unused Blocks...........................0

Unused Bytes............................0

Last Used Ext FileId....................5

Last Used Ext BlockId...................768

Last Used Block.........................128

*************************************************

The segment is analyzed

0% -- 25% free space blocks.............0

0% -- 25% free space bytes..............0

25% -- 50% free space blocks............1

25% -- 50% free space bytes.............8192

50% -- 75% free space blocks............0

50% -- 75% free space bytes.............0

75% -- 100% free space blocks...........17

75% -- 100% free space bytes............139264

Unused Blocks...........................0

Unused Bytes............................0

Total Blocks............................604

Total bytes.............................4947968

PL/SQL procedure successfully completed.

 

SQL> select TABLE_NAME,BLOCKS,NUM_ROWS from user_tables where table_name='T1';

TABLE_NAME                         BLOCKS   NUM_ROWS

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

T1                                    622        605

 

手工设置了统计信息以后,可以骗过cost based analysis of direct path i/o

 

6  how to disable this  feature

So I had a research for a couple of hours and found how to disable it. Oracle 11g has introduced 10949 event to control this.
Don’t forget 10949 event when you want to disable this great feature for any reason!

alter session set events '10949 trace name context forever, level 1';
alter system set event= '10949 trace name context forever, level 1' scope=spfile;

Footnote1:What you should keep in mind is that this is not a CBO feature but a runtime execution engine feature. It would always show the same execution plan – TABLE ACCESS FULL. When the execution engine runs this operation, it determines how to read the table(direct path read or conventional path read) considering various factors.

Footnote2:There is “_serial_direct_read” parameter which forces the full scan on the big table to be a direct read – The opposite of 10949 event.
--摘录自Disabling direct path read for the serial full table scan11g

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/758322/viewspace-718274/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/758322/viewspace-718274/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值