设为首页 收藏本站
查看: 615|回复: 0

[经验分享] 谈谈Oracle direct path read和direct path write

[复制链接]
YunVN网友  发表于 2016-8-15 06:31:44 |阅读模式
顾名思义,Oracle 进行direct path read和direct path write操作时,将会绕过buffer_cache,直接将数据读至PGA中。Oracle官方文档也似乎这么说。
但事实果真是这样吗?
接下来分2部分测试,首先测试direct path read,我们知道Oracle并行读时将会产生进行direct path read

SQL> alter system flush buffer_cache;

System altered.

SQL> select /*+ parallel(a 10)*/ * from zhoultest a;

835328 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1476512502

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

| Id  | Operation            | Name      | Rows  | Bytes | Cost (%CPU)| Time
|    TQ  |IN-OUT| PQ Distrib |

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

|   0 | SELECT STATEMENT     |           |   832K|    62M|   405   (2)| 00:00:05
|        |      |            |

|   1 |  PX COORDINATOR      |           |       |       |            |
|        |      |            |

|   2 |   PX SEND QC (RANDOM)| :TQ10000  |   832K|    62M|   405   (2)| 00:00:05
|  Q1,00 | P->S | QC (RAND)  |

|   3 |    PX BLOCK ITERATOR |           |   832K|    62M|   405   (2)| 00:00:05
|  Q1,00 | PCWC |            |

|   4 |     TABLE ACCESS FULL| ZHOULTEST |   832K|    62M|   405   (2)| 00:00:05
|  Q1,00 | PCWP |            |

--------------------------------------------------------------------------------
-------------------------------
可以看到buffer_cache中只有segment head
SQL> select a.FILE#,a.BLOCK#,b.EXTENT_ID,b.BLOCK_ID,b.blocks,a.DIRTY from v$bh a, dba_extents b where a.file#=b.file_id and a.block# between b.block_id and b.block_id+b.blocks-1
and owner='ZHOUL' and SEGMENT_NAME='ZHOULTEST' and a.status<>'free';
  2  
     FILE#     BLOCK#  EXTENT_ID   BLOCK_ID     BLOCKS D
---------- ---------- ---------- ---------- ---------- -
         7       5131          0       5129          8 N
         
         
SQL> select header_file,header_block from dba_segments where owner='ZHOUL' and SEGMENT_NAME='ZHOULTEST';

HEADER_FILE HEADER_BLOCK
----------- ------------
          7         5131
进一步dump segment head
SQL>  alter system  dump datafile 7 block 5131;

System altered.
可以看到segment head中有HighWater Mark和Extent Map,而Oracle全表扫描时,正是通过Extent Map定位数据块,扫描至高水位以下位置。需要注意的是当表格extent很多时,
不足以放在同一个block中时,就会出现多个区位图块(小表的区位图块和segment head是同一个数据块,如本例),这时就需要一个指针指向下一个区位图块。
用Map Header:: next 0x00000000可以看出,本例中下一个区位图块为空,即只有一个区位图块。
  Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 118    #blocks: 32896
                  last map  0x00000000  #maps: 0      offset: 2716  
      Highwater::  0x01c0e609  ext#: 117    blk#: 1024   ext size: 1024  
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 32896
  mapblk  0x00000000  offset: 117   
                   Unlocked
  --------------------------------------------------------
  Low HighWater Mark :
      Highwater::  0x01c0e609  ext#: 117    blk#: 1024   ext size: 1024  
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 32896
  mapblk  0x00000000  offset: 117   
  Level 1 BMB for High HWM block: 0x01c0e20c
  Level 1 BMB for Low HWM block: 0x01c0e20c
  --------------------------------------------------------
  Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0      
  L2 Array start offset:  0x00001434
  First Level 3 BMB:  0x00000000
  L2 Hint for inserts:  0x01c0140a
  Last Level 1 BMB:  0x01c0e20c
  Last Level II BMB:  0x01c0140a
  Last Level III BMB:  0x00000000
     Map Header:: next  0x00000000  #extents: 118  obj#: 72659  flag: 0x10000000
  Inc # 0
  Extent Map
  -----------------------------------------------------------------
   0x01c01409  length: 8     
   0x01c01411  length: 8     
   0x01c01419  length: 8     
   0x01c01421  length: 8  
。。。
通过以上测试我们可以推断出,Oracle在进行并行表格扫描时,需要将表格头和区位图块载入buffer_cache中,通过读取表格头的高水位标记位
和区位图块的区信息,从而定位表格数据块在数据文件中的位置,进而读取数据。
在测试中我们还同时发现了另外两个现象:
(1)Oracel扫描dba_extents(最终对x$ktfbue表格扫描)时,其实就是去读取区位图块的区信息,通过以下测试可以说明这一点。
通过bbed物理修改位图块信息
BBED> modify 0x0a
Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y
File: /oradata/mcstar/zhoul01.dbf (0)
Block: 5131             Offsets:  284 to  795           Dba:0x00000000
------------------------------------------------------------------------
0a000000 1114c001 08000000 1914c001 08000000 2114c001 08000000 2914c001
再次查询dba_extents视图,可以观察到数据发生了变化
SQL> select EXTENT_ID,FILE_ID,BLOCK_ID,BLOCKS from dba_extents where SEGMENT_NAME='ZHOULTEST' and OWNER='ZHOUL' order by 1;

EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
---------- ---------- ---------- ----------
         0          7       5129         10

(2)Oracle在并行扫描时,将会进行表格级别的checkpoint。
Oracle使用direct path read进行并行查询,即直接从数据文件读取数据至PGA,如果有数据存在于buffer_cache时,势必会影响数据的一致性。所以在在并行扫描时,将会进行表格级别的checkpoint。
以下测试证明了这一点。
首先改变一些数据块
SQL> update  zhoultest set name=lower(name) where rownum<10000;

9999 rows updated.

SQL> commit;

Commit complete.

SQL> select count(*) from v$bh a, dba_extents b where a.file#=b.file_id and a.block# between b.block_id and b.block_id+b.blocks-1
  2  and owner='ZHOUL' and SEGMENT_NAME='ZHOULTEST' and a.status<>'free' and a.dirty='Y';

  COUNT(*)
----------
       116
发起一个并行查询
select /*+ parallel(a 10)*/ * from zhoultest a where rownum<0;
再次查询,可以看到dirty数据块已经从buffer_cache中刷往数据文件中。
SQL> /

  COUNT(*)
----------
         0   
进一步dump buffer_cache中,我们注意到了objq,正是通过这个objq,Oracle加快了在buffer_cache中搜索对象的速度,同理ckptq的存在加快了增量checkpoint的内存搜索效率,
fileq的存在加快了表空间checkpoint的内存搜索效率。
SQL> ALTER SESSION SET EVENTS 'immediate trace name buffers level 2';

Session altered.


BH (0x213f5030) file#: 7 rdba: 0x01c0390c (7/14604) class: 1 ba: 0x2128e000
  set: 6 blksize: 8192 bsi: 0 set-flg: 0 pwbcnt: 0
  dbwrid: 0 obj: 76226 objn: 76226 tsn: 8 afn: 7
  hash: [20fedda0,2a693b68] lru: [22fefd88,213f23b8]
  obj-flags: object_ckpt_list
  ckptq: [22fed090,2a6e3260] fileq: [2a6e32ec,2a6e32ec] objq: [2603ca30,2603ca30]
  st: XCURRENT md: NULL tch: 1
  flags: buffer_dirty gotten_in_current_mode redo_since_read
  LRBA: [0x9331.ede6.0] HSCN: [0xa00.e7f7af9] HSUB: [1]
  buffer tsn: 8 rdba: 0x01c0390c (7/14604)
  scn: 0x0a00.0e7f7af9 seq: 0x02 flg: 0x02 tail: 0x7af90602
  frmt: 0x02 chkval: 0x0000 type: 0x06=trans data

需要注意的是,在Oracle 9i中,并没有objq存在
BH (0x0x53fc77ac) file#: 9 rdba: 0x02410873 (9/67699) class 1 ba: 0x0x5360a000
  set: 6 dbwrid: 0 obj: 44558 objn: 44558
  hash: [83519fa8,83519fa8] lru: [53fc767c,53fc796c]
  LRU flags: moved_to_tail
  ckptq: [NULL] fileq: [NULL]
  st: XCURRENT md: NULL rsop: 0x(nil) tch: 0
  flags: only_sequential_access
  LRBA: [0x0.0.0] HSCN: [0xffff.ffffffff] HSUB: [255] RRBA: [0x0.0.0]
  buffer tsn: 9 rdba: 0x02410873 (9/67699)
  scn: 0x0a00.06200be8 seq: 0x01 flg: 0x04 tail: 0x0be80601
  frmt: 0x02 chkval: 0x4d10 type: 0x06=trans data
我们知道drop table时,也会进行表格级别ckpt,当drop table时,需要在buffer_cache中搜寻和这张表格相关的数据块,如果在高并发Oracle9i环境下,极易引起latch争用,
如lacth:cache buffer chain等。


我们知道在insert时,加hint:/*+ append*/将会执行direct path write,即Oracle绕过buffer_cache,直接写往数据文件。是不是Oracle所有的
数据块都绕过buffer_cache都写往数据文件呢?
接下来继续测试direct path write。
为避免干扰,我们从sys.t1读取内容插往zhoultest表格
SQL> explain plan for insert /*+ append*/ into zhoultest  select * from sys.t1;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1069440229

--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | INSERT STATEMENT   |           | 51050 |    63M|   143   (4)| 00:00:02 |
|   1 |  LOAD AS SELECT    | ZHOULTEST |       |       |            |          |
|   2 |   TABLE ACCESS FULL| T1        | 51050 |    63M|   143   (4)| 00:00:02 |
--------------------------------------------------------------------------------

9 rows selected.

SQL> alter system flush buffer_cache;

System altered.

SQL> insert /*+ append*/ into zhoultest  select * from sys.t1;

420896 rows created.

SQL> commit;

Commit complete.

我们看到在buffer_cache中除了segment head还出现了其他数据块。
SQL> select a.FILE#,a.BLOCK#,b.EXTENT_ID,b.BLOCK_ID,b.blocks,a.DIRTY from v$bh a, dba_extents b where a.file#=b.file_id and a.block# between b.block_id and b.block_id+b.blocks-1
and owner='ZHOUL' and SEGMENT_NAME='ZHOULTEST' and a.status<>'free';
  2  
     FILE#     BLOCK#  EXTENT_ID   BLOCK_ID     BLOCKS D
---------- ---------- ---------- ---------- ---------- -
         7       5131          0       5129          8 Y
         7       5130          0       5129          8 Y
         7      24844        101      24841       1024 Y
         7      29962        102      29961       1024 Y
         7      29964        102      29961       1024 Y
         7      29961        102      29961       1024 Y
         7      29963        102      29961       1024 Y
         7      30986        103      30985       1024 Y
         7      30988        103      30985       1024 Y
         7      30985        103      30985       1024 Y
         7      30987        103      30985       1024 Y

     FILE#     BLOCK#  EXTENT_ID   BLOCK_ID     BLOCKS D
---------- ---------- ---------- ---------- ---------- -
         7      32010        104      32009       1024 Y
         7      32012        104      32009       1024 Y
         7      32009        104      32009       1024 Y
         7      32011        104      32009       1024 Y
         7      33036        105      33033       1024 Y
         7      33033        105      33033       1024 Y
         7      33035        105      33033       1024 Y
         7      33034        105      33033       1024 Y
         7      34057        106      34057       1024 Y
         7      34059        106      34057       1024 Y
         7      34058        106      34057       1024 Y

     FILE#     BLOCK#  EXTENT_ID   BLOCK_ID     BLOCKS D
---------- ---------- ---------- ---------- ---------- -
         7      34060        106      34057       1024 Y

23 rows selected.
进一步dump数据块,可以看出是2级位图块
Dump of Second Level Bitmap Block
   number: 230     nfree: 21      ffree: 138    pdba:     0x01c0140b
   Inc #: 0 Objd: 72659
  opcode:0
xid:
  L1 Ranges :
  --------------------------------------------------------
   0x01c01409  Free: 1 Inst: 1
   0x01c01419  Free: 1 Inst: 1
   0x01c01429  Free: 1 Inst: 1
   0x01c01439  Free: 1 Inst: 1
   0x01c01449  Free: 1 Inst: 1
。。。
继续dump其他数据块,看出是1级位图块

SQL> alter system dump datafile 7 block 34060;

System altered.

Dump of First Level Bitmap Block
--------------------------------
   nbits : 4 nranges: 1         parent dba:  0x01c0140a   poffset: 185   
   unformatted: 97      total: 256       first useful block: 0      
   owning instance : 1
   instance ownership changed at
   Last successful Search
   Freeness Status:  nf1 0      nf2 0      nf3 0      nf4 0      

   Extent Map Block Offset: 4294967295
   First free datablock : 159   
   Bitmap block lock opcode 0
   Locker xid:     :  0x0000.000.00000000
   Inc #: 0 Objd: 72659
  HWM Flag: HWM Set
      Highwater::  0x01c088a8  ext#: 106    blk#: 927    ext size: 1024  
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 21535
  mapblk  0x00000000  offset: 106   
。。。

通过以上测试我们可以得出以上推论,在进行direct path write时,由于要改变数据块内容,Oracle需要将反映数据块位置状态的L3,L2,L1,SEGMENT_HEAD读至buffer_cache中。
需要注意的是当进行direct path write时,Oracle会将segment的low hwm至high hwm未格式化的block进行格式化操作,即low hwm=high hwm,然后在high hwm之后插数据
直接路径插入之前
   Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 119    #blocks: 33920
                  last map  0x00000000  #maps: 0      offset: 2716  
      Highwater::  0x01c0f309  ext#: 118    blk#: 1024   ext size: 1024  
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 33916
  mapblk  0x00000000  offset: 118   
                   Unlocked
  --------------------------------------------------------
  Low HighWater Mark :
      Highwater::  0x01c0ef19  ext#: 118    blk#: 16     ext size: 1024  
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 32908
  mapblk  0x00000000  offset: 118   
  Level 1 BMB for High HWM block: 0x01c0ef0c
  Level 1 BMB for Low HWM block: 0x01c0ef09
仅直接路径插入一行数据
SQL> insert /*+ append*/ into zhoultest  select * from sys.t1 where rownum<2;

1 row created.

SQL> commit;

Commit complete.

再次查看segment head,可以看到high Highwater mask= Low HighWater Mark
Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 120    #blocks: 34944
                  last map  0x00000000  #maps: 0      offset: 2716  
      Highwater::  0x01c0f40e  ext#: 119    blk#: 5      ext size: 1024  
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 33925
  mapblk  0x00000000  offset: 119   
      Disk Lock:: Locked by xid:  0x002a.021.00000822
  --------------------------------------------------------
  Low HighWater Mark :
      Highwater::  0x01c0f40e  ext#: 119    blk#: 5      ext size: 1024  
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 33925
  mapblk  0x00000000  offset: 119   
  Level 1 BMB for High HWM block: 0x01c0f409
  Level 1 BMB for Low HWM block: 0x01c0f409

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-257735-1-1.html 上篇帖子: IMP和EXP命令(Oracle数据导入导出) 下篇帖子: Oracle中的数据字典技术及常用数据字典总结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表