• Oracle 11g 中 Direct path reads 特性 说明


    一.DirectPath Reads 说明

    在oracle 11g以前的版本中,如果对大表进行全表扫描,wait event是:db file scattered read;在11g中,如果对大表进行全表扫描,wait event是:direct path read;即在11g中,大表全表扫描是将数据块直接读入会话的pga区域。(具体的查看方法参考后面的示例)。

                在11g中,大表全表扫描时数据块不经过sga而直接进pga,这样会造成每次进行大表全表扫描,物理读都是很大,而在10g中,由于全表扫描的数据块在sga中已经存在,所以执行全表扫描时,它的物理读为0。

                但是这里主要是oracle在优化策略上的进步,即假定大表频繁全表扫描这种现象,在生产库上不会太多,通过把数据直接读入pga,进而减少了cachebuffer的繁忙交换程度,提高了cachebuffer的使用效率.

    direct path read具备更多的优势:

    1. 减少了对栓的使用,避免可能的栓争用

    2. 物理IO的大小不再取决于buffer_cache中所存在的块;试想某个8个块的extent中1,3,5,7号块在高速缓存中,而2,4,6,8块没有被缓存,传统的方式在读取该extent时将会是对2,4,6,8块进行4次db file sequential read,这是一种十分可怕的状况,其效率往往要比单次读取这个区间的所有8个块还要低得多,虽然Oracle为了避免这种情况总是尽可能的不缓存大表的块(读入后总是放在队列最冷的一端);而direct path read则可以完全避免这类问题,尽可能地单次读入更多的物理块。

    direct path read也会引入一些缺点:

    1.在直接路径读取某段前需要对该对象进行一次段级的检查点(A segmentcheckpoint).

    2.可能导致重复的延迟块清除操作.

    该部分引用Maclean 的Blog:

    直接路径读取对于延迟块清除的影响

    http://www.oracledatabase12g.com/archives/direct-read-impact-on-delayed-block-read.html

    MOS 上的说明:High 'direct path read' waits in 11g [ID 793845.1]

    There have beenchanges in 11g in the heuristics to choose between direct path reads or readsthrough buffer cache for serial table scans. 

    In 10g, serialtable scans for "large" tables used to go through cache (by default)which is not the case anymore.  In 11g, this decision to read viadirect path or through cache is based on the size of the table, buffer cachesize and various other stats. 

    Direct path reads are faster than scattered reads andhave less impact on other processes because they avoid latches.

    二.相关等待事件说明

    Oracle 常见的33个等待事件

    http://blog.csdn.net/tianlesoftware/article/details/5807800

    2.1 查看等待事件分类情况:

    /* Formatted on 2010/8/11 16:08:55 (QP5v5.115.810.9015) */

      SELECT   wait_class#,

               wait_class_id,

               wait_class,

               COUNT ( * ) AS "count"

        FROM   v$event_name

    GROUP BY   wait_class#, wait_class_id, wait_class

    ORDER BY   wait_class#;

    WAIT_CLASS# WAIT_CLASS_IDWAIT_CLASS                count

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

              0    1893977003Other                       717

              1    4217450380Application                  17

              2    3290255840Configuration                24

              3    4166625743Administrative               54

              4    3875070507Concurrency                  32

              5    3386400367Commit                        2

              6    2723168908Idle                         94

              7    2000153315Network                      35

              8    1740759767UserI/O                     45

              9    4108307767SystemI/O                   30

             10    2396326234Scheduler                     7

             11    3871361733Cluster                      50

             12     644977587Queueing                      9

    2.2 Db file scattered read 等待事件

    这个等待事件在实际生产库中经常可以看到,这是一个用户操作引起的等待事件,当用户发出每次I/O需要读取多个数据块这样的SQL 操作时,会产生这个等待事件,最常见的两种情况是全表扫描(FTS: Full Table Scan)和索引快速扫描(IFFS: index fast full scan)。

    这个名称中的scattered( 发散),可能会导致很多人认为它是以scattered 的方式来读取数据块的,其实恰恰相反,当发生这种等待事件时,SQL的操作都是顺序地读取数据块的,比如FTS或者IFFS方式(如果忽略需要读取的数据块已经存在内存中的情况)。

    这里的scattered指的是读取的数据块在内存中的存放方式,他们被读取到内存中后,是以分散的方式存在在内存中,而不是连续的。

    这个等待事件有三个参数:

    File#: 要读取的数据块所在数据文件的文件号。

    Block#: 要读取的起始数据块号。

    Blocks:需要读取的数据块数目。

    2.3 Direct path read 等待事件

    这个等待事件发生在会话将数据块直接读取到PGA当中,而不是SGA中的情况,这些被读取的数据通常是这个会话私有的数据,所以不需要放到SGA作为共享数据,因为这样做没有意义。这些数据通常是来自与临时段上的数据,比如一个会话中SQL的排序数据,并行执行过程中间产生的数据,以及Hash Join,merge join产生的排序数据,因为这些数据只对当前的会话的SQL操作有意义,所以不需要放到SGA当中。

    当发生direct path read等待事件时,意味着磁盘上有大量的临时数据产生,比如排序,并行执行等操作。 或者意味着PGA中空闲空间不足。

    这个等待事件有三个参数:

    Descriptoraddress:       一个指针,指向当前会话正在等待的一个direct read I/O。

    First dba: descriptor address 中最旧的一个I/O数据块地址。

    Block cnt: descriptor address上下文中涉及的有效的buffer 数量。

    2.4 Direct path write 等待事件

    这个等待事件和direct path read 正好相反,是会话将一些数据从PGA中直接写入到磁盘文件上,而不经过SGA。

    这种情况通常发生在:

    使用临时表空间排序(内存不足)

    数据的直接加载(使用append方式加载数据)

    并行DML操作。

    这个等待事件有三个参数:

                Descriptoraddress: 一个指针,指向当前会话正在等待的一个direct I/O.

                Firstdba: descriptor address 中最旧的一个I/O数据块地址。

                Blockcnt: descriptor address 上下文中涉及的有效地 buffer 数量。

    更多链接参考:

    db file sequential read

    http://sharklove.itpub.net/post/660/279770

    db file scattered read

    http://sharklove.itpub.net/post/660/279771

    direct path write(USER I/0类)

    http://sharklove.itpub.net/post/660/279774

    direct path read(USER I/0类)

    http://sharklove.itpub.net/post/660/279772

    三.示例说明

    Oracle 查看session 当前统计信息 脚本 说明

    http://blog.csdn.net/tianlesoftware/article/details/7689450

    Oracle 执行计划(ExplainPlan) 说明

    http://blog.csdn.net/tianlesoftware/article/details/5827245

    3.1 Oracle 11gR2 示例

    SQL> show user

    USER is "ANQING"

    SQL> create table dave as select rownumrn,rpad('A',600,'Z') rp from dual connect by level <=300000;

    Table created.

    SQL> set linesize 200 pagesize 1400;

    SQL> select count(*) from dave;

     COUNT(*)

    ----------

       300000

    SQL> col name for a50

    SQL> SELECT vm.sid, vs.name, vm.VALUE

     2    FROM v$mystat vm, v$sysstatvs

     3   WHERE     vm.statistic# = vs.statistic#

     4         AND vs.name IN

     5                ('cleanouts only- consistent read gets',

     6                 'session logicalreads',

     7                 'physicalreads',

     8                 'physical readsdirect',

     9                 'redo size');

          SID NAME                                                    VALUE

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

          139 session logical reads                                   83269

          139 physical reads                                          32505

           139 physical reads direct                                   27273

          139 redo size                                             577392

          139 cleanouts only - consistent read gets                       4

    --查看执行计划:

    SQL> set autotrace on

    SQL> select count(*) from dave;

     COUNT(*)

    ----------

       300000

    Execution Plan

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

    Plan hash value: 1718719579

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

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

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

    |   0| SELECT STATEMENT   |      |    1 |  7461   (1)| 00:01:30 |

    |   1|  SORT AGGREGATE    |     |     1 |            |         |

    |   2|   TABLE ACCESS FULL| DAVE |   254K| 7461   (1)| 00:01:30 |

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

    Note

    -----

       -dynamic sampling used for this statement (level=2)

    Statistics

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

             4  recursive calls

             0  db block gets

         27343  consistent gets

         27273  physical reads

             0  redo size

           527  bytes sent via SQL*Net toclient

           520  bytes received via SQL*Netfrom client

             2  SQL*Net roundtrips to/fromclient

             0  sorts (memory)

             0  sorts (disk)

             1  rows processed

    SQL>

    3.2 Oracle 10gR2 测试

    SQL> select * from v$version;

    BANNER

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

    Oracle Database 10g Enterprise EditionRelease 10.2.0.4.0 - Prod

    PL/SQL Release 10.2.0.4.0 - Production

    CORE   10.2.0.4.0      Production

    TNS for Linux: Version 10.2.0.4.0 -Production

    NLSRTL Version 10.2.0.4.0 - Production

    SQL> create table dave as select rownumrn,rpad('A',600,'Z') rp from dual connect by level <=300000;

    Table created.

    SQL> col name for a50

    SQL> SELECT vm.sid, vs.name, vm.VALUE

     2    FROM v$mystat vm, v$sysstatvs

     3   WHERE     vm.statistic# = vs.statistic#

     4         AND vs.name IN

     5                ('cleanouts only- consistent read gets',

     6                 'session logicalreads',

     7                 'physicalreads',

     8                 'physical readsdirect',

     9                 'redo size');

          SID NAME                                                   VALUE

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

          167 session logical reads                                   30345

          167 physical reads                                             13

           167 physical readsdirect                                      0

          167 redo size                                             247320

          167 cleanouts only - consistent read gets                       0

    --注意这里的physicalreads direct 0

    SQL> set autotrace on;

    seSQL  

    SQL> select count(*) from dave;

     COUNT(*)

    ----------

       300000

    Execution Plan

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

    Plan hash value: 1718719579

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

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

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

    |   0| SELECT STATEMENT   |      |    1 |  7421   (1)| 00:01:30 |

    |   1|  SORT AGGREGATE    |     |     1 |            |          |

    |   2|   TABLE ACCESS FULL| DAVE |   280K| 7421   (1)| 00:01:30 |

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

    Note

    -----

       -dynamic sampling used for this statement

    Statistics

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

            28  recursive calls

             0  db block gets

         27359  consistent gets

         27304  physical reads

             0  redo size

            411 bytes sent via SQL*Net to client

           400  bytes received via SQL*Netfrom client

             2  SQL*Net roundtrips to/fromclient

             0  sorts (memory)

             0  sorts (disk)

             1  rows processed

    SQL>

    四.相关的BUG

    在Oracle 11g中使用direct path read可以把数据直接读入pga,进而减少了cachebuffer的繁忙交换程度,提高了cachebuffer的使用效率. 但是避开了SGA的过程也导致不能使用sga 的buffer cache。

                在MOS上有一篇与Direct Read 相关的bug,MOS如下:KEEP BUFFER POOL Does Not Work for LargeObjects on 11g [ID 1081553.1]

    4.1 Symptoms

    While doing fulltable scan, Buffer Cache KEEP pool is not being used to read the blocks of a(KEEP) table which size is >10% of  DB_KEEP_CACHE_SIZE. 

    --Oracle 11gR1中,当我们做全表扫描时,如果需要读取的block大于DB_KEEP_CACHE_SIZE10%,那么buffercache Keep pool就不会被使用。

    Theseblocks are always being read through DIRECT READ, which can causeperformance problem due to non-caching / re-reading of keep object blocks.

    --扫描的block会使用direct read,这样会导致性能问题。

    4.2 Cause

    The problem is caused by Bug8897574 - KEEP BUFFER POOL DOES NOT WORK

    The issue is fixed in 12.1 and the fix isincluded in patch set 11.2.0.2 and higher.

    --导致上面问题的是因为Bug 8897574,在Oracle 12.111.2.0.2中,已经修复了这个bug

    Due to this bug,tables with size >10% of cache size, were being treated as 'largetables' for their reads and this resulted in execution of a newSERIAL_DIRECT_READ path in 11g.

    4.3 Solution

    Download and apply Patch 8897574 for 11.1.0.7 or 11.2.0.1 for your actualPSU level.

    OR

    Upgrade to 11.2.0.2 or higher

    With the bug fix applied, any object in theKEEP buffer pool, whose size is less than DB_KEEP_CACHE_SIZE, is considered asa small or medium sized object. This will cache the read blocks and avoidsubsequent direct read for these objects .

    @ As per development update in the bugreport, to workaround this issue we can set Event10949 at level 1.

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

    版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

    Skype:            tianlesoftware

    QQ:                 tianlesoftware@gmail.com

    Email:             tianlesoftware@gmail.com

    Blog:   http://www.tianlesoftware.com

    Weibo:            http://weibo.com/tianlesoftware

    Twitter: http://twitter.com/tianlesoftware

    Facebook: http://www.facebook.com/tianlesoftware

    Linkedin: http://cn.linkedin.com/in/tianlesoftware

    -------加群需要在备注说明Oracle表空间和数据文件的关系,否则拒绝申请----

    DBA1 群:62697716(满);   DBA2 群:62697977(满)  DBA3 群:62697850(满)  

    DBA 超级群:63306533(满);  DBA4 群:83829929   DBA5群: 142216823

    DBA6 群:158654907    DBA7 群:172855474   DBA总群:104207940

    道森Oracle,国内最早、最大的网络语音培训机构,我们提供专业、优质的Oracle技术培训和服务! 我们的官方网站:http://www.daosenoracle.com 官方淘宝店:http://daosenpx.taobao.com/
  • 相关阅读:
    Design Pattern Explained
    StringBuilder or StringBuffer
    Algorithms
    Difference between pages and blocks
    Date Time Calendar
    Math if fun
    Sublime Text
    Java Regex
    Learning C
    跨域通信/跨域上传浅析
  • 原文地址:https://www.cnblogs.com/tianlesoftware/p/3609255.html
Copyright © 2020-2023  润新知