首页 技术 正文
技术 2022年11月15日
0 收藏 799 点赞 2,826 浏览 10812 个字

㈠ 直接路径加载和buffer cache
       
       直接路径插入的数据不经过buffer cache,从PGA直接把数据格式化成Oracle块
       然后由普通的Oracle Server Process进程把数据块写入数据文件
       因为不经过buffer cache,所以不需要DBWn介入
       
       假如有表a,现要将a中的数据插入表b,在普通的插入下,需先将a的数据块I/O到buffer cache
       在buffer cache中从a的块中读出行,插进b的块中
       此时,b的块就都变成了脏块,再等待DBWn把他们flush到数据文件
       因此,普通插入后,a表和b表的块都会在buffer cache中出现
       
       而直接路径插入,将a表的数据块I/O到buffer cache,读出行,直接写进b表所在的数据文件
       插入完成后,除了表头块外,b表的数据块并未在buffer cache中出现过

测试:

  1. hr@ORCL> create table a (id number,name varchar2(10));
  2. Table created.
  3. hr@ORCL> create table b (id number,name varchar2(10));
  4. Table created.
  5. hr@ORCL> insert into a values(1,’aa’);
  6. 1 row created.
  7. hr@ORCL> insert into a values(2,’bb’);
  8. 1 row created.
  9. hr@ORCL> insert into a values(3,’cc’);
  10. 1 row created.
  11. hr@ORCL> insert into a values(4,’dd’);
  12. 1 row created.
  13. hr@ORCL> commit;
  14. Commit complete.
  15. hr@ORCL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from a;
  16. DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
  17. ———————————— ————————————
  18. 4                                  508
  19. 4                                  508
  20. 4                                  508
  21. 4                                  508
  22. –现在a表有4行,占用块508,而目前b表还木有数据
  23. –将buffer cache清空
  24. hr@ORCL> alter system flush buffer_cache;
  25. System altered.
  26. –先用直接路径插入,从a表向b表插入数据
  27. hr@ORCL> insert /*+ append */ into b select * from a;
  28. 4 rows created.
  29. hr@ORCL> commit;
  30. Commit complete.
  31. –使用v$bh查看buffer cache中的块
  32. hr@ORCL> select file#,block# from v$bh where objd=(select data_object_id from user_objects where object_name=’A’);
  33. FILE#     BLOCK#
  34. ———- ———-
  35. 4        508     ←←当前包含数据的块
  36. 4        508     ←←当前包含数据的块
  37. 4        511
  38. 4        511
  39. 4        506
  40. 4        509
  41. 4        509
  42. 4        512
  43. 4        512
  44. 4        507
  45. 4        507
  46. 4        510
  47. 4        510
  48. 4        505
  49. 14 rows selected.
  50. –这是因为对a表进行全表扫,a表中低高水位点下所有的块都被读进buffer cache,这其中当然也包括508了
  51. hr@ORCL> select file#,block# from v$bh where objd=(select data_object_id from user_objects where object_name=’B’);
  52. FILE#     BLOCK#
  53. ———- ———-
  54. 4       2571
  55. 4       2569
  56. 4       2570
  57. hr@ORCL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from b;
  58. DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
  59. ———————————— ————————————
  60. 4                                 2572
  61. 4                                 2572
  62. 4                                 2572
  63. 4                                 2572
  64. –上面两个查询可以看到,b表中的数据占用地2572块,但是,直接路径插入后,2572并没有被调入buffer cache
  65. –buffer cache中只有2569 2570 2571
  66. –其中2571是段头块(select header_file,header_block from dba_segments where segment_name=’B’)
  67. –2570 2569则是L1 L2这两个位图块
  68. –接下来使用普通插入
  69. hr@ORCL> alter system flush buffer_cache;
  70. System altered.
  71. hr@ORCL> insert into b select * from a;
  72. 4 rows created.
  73. hr@ORCL> commit;
  74. Commit complete.
  75. hr@ORCL> select file#,block# from v$bh where objd=(select data_object_id from user_objects where object_name=’B’);
  76. FILE#     BLOCK#
  77. ———- ———-
  78. 4       2571
  79. 4       2574
  80. 4       2569
  81. 4       2575
  82. 4       2570
  83. 4       2570
  84. 4       2573
  85. 4       2576  ←←本次普通插入的数据所在的块
  86. 8 rows selected.
  87. hr@ORCL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from b;
  88. DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
  89. ———————————— ————————————
  90. 4                                 2572
  91. 4                                 2572
  92. 4                                 2572
  93. 4                                 2572
  94. 4                                 2576
  95. 4                                 2576
  96. 4                                 2576
  97. 4                                 2576
  98. 8 rows selected.

从上面的实验可以证明,普通插入,要先将数据块传进buffer cache
       这是Oracle通常修改数据的方式,不对数据文件直接进行修改,而是在内存中完成修改,再由日志提供保护
       对于小量的修改,这是种可取的方法,但对于大数据交易,直接路径将可以提供更好的性能
       
       还有就是,直接路径加载是在高水位之上完成的插入动作,因此无论高水位下有多少空闲块都会被忽略,段空间将会随之增大

㈡ 直接路径加载和undo
     
       差别比较明显的是undo(直接路径几乎没有undo),俩者redo差不多(普通插入稍微多点redo,因为Oracle需要redo来保护undo)
       直接路径用HWM回滚,普通插入用undo回滚

  1. –再次向b表使用直接路径插入
  2. hr@ORCL> insert /*+ append */ into b select id+4,name from a;
  3. 4 rows created.
  4. –查看事务信息
  5. hr@ORCL> select xidusn,xidslot,xidsqn,ubafil,ubablk,ubasqn from v$transaction;
  6. XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK     UBASQN
  7. ———- ———- ———- ———- ———- ———-
  8. 10         23        314          0          0          0
  9. –因为当前只有一个事务,因此选择v$transaction视图时没有加条件
  10. –从上面的显示结果可以看到,ubafil ubablk为0,也就是,此事务没有对应的回滚块
  11. –只有在回滚段头的事务表中占用了一行而已

那么直接路径插入是如何提供回滚的呢?观察b表的HWM的变化,就可以解答这个问题

  1. –查找b表的HWM
  2. hr@ORCL> select header_file,header_block from dba_segments where segment_name=’B’;
  3. HEADER_FILE HEADER_BLOCK
  4. ———– ————
  5. 4         2571
  6. hr@ORCL> alter session set tracefile_identifier=’hr_2571′;
  7. Session altered.
  8. hr@ORCL> alter system dump datafile 4 block 2571;
  9. System altered.
  10. –trc文件摘入如下:
  11. Extent Control Header
  12. —————————————————————–
  13. Extent Header:: spare1: 0      spare2: 0      #extents: 2      #blocks: 16
  14. last map  0x00000000  #maps: 0      offset: 2716
  15. Highwater::  0x01000a11  ext#: 0      blk#: 8      ext size: 8
  16. #blocks in seg. hdr’s freelists: 0
  17. #blocks below: 8
  18. mapblk  0x00000000  offset: 0
  19. Unlocked
  20. ——————————————————–
  21. Low HighWater Mark :
  22. Highwater::  0x01000a11  ext#: 0      blk#: 8      ext size: 8
  23. –高水位点是4号文件2577号块
  24. –提交后查看直接路径插入到哪个块中
  25. hr@ORCL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from b where id>=8;
  26. DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
  27. ———————————— ————————————
  28. 4                                 2577
  29. –通过上面的查询,本次直接路径插入,数据被存进2577号块,而提交的HWM正是2577
  30. |————–|——–|——–|———-
  31. |数据块 …… |2575|2576|2577|2578|…
  32. |————–|——–|——–|———-
  33. 此处是高水位点,直接路径插入从此块开始分配空间
  34. –直接路径插入,是在高水位点之上分配临时段,将数据插入时进入此临时段
  35. –在提交后将高水位点提升至临时段之上
  36. –现在已经提交,再来看高水位点的信息
  37. hr@ORCL> alter system dump datafile 4 block 2571;
  38. System altered.
  39. –trc文件摘入如下:
  40. Extent Control Header
  41. —————————————————————–
  42. Extent Header:: spare1: 0      spare2: 0      #extents: 2      #blocks: 16
  43. last map  0x00000000  #maps: 0      offset: 2716
  44. Highwater::  0x01000a12  ext#: 1      blk#: 1      ext size: 8
  45. #blocks in seg. hdr’s freelists: 0
  46. #blocks below: 9
  47. mapblk  0x00000000  offset: 1
  48. Unlocked
  49. ——————————————————–
  50. Low HighWater Mark :
  51. Highwater::  0x01000a12  ext#: 1      blk#: 1      ext size: 8
  52. –第一次dump是Highwater::  0x01000a11,而现在是 Highwater::  0x01000a12
  53. –高水位点升至2578块,如下图
  54. |————–|——–|——–|——–|—–
  55. |数据块 ……  |2575  |2576|2577|2578|
  56. |————–|——–|——–|——–|—–
  57. 高水位点上升至此处
  58. –再试一次直接路径插入回滚时的情况
  59. –先猜想一下,此次插入应该插入到2578,如果提交的话,就提升高水位点到2579,如果回滚的话,保持高水位点不变
  60. hr@ORCL> insert /*+ append */ into b select id+4,name from a;
  61. 4 rows created.
  62. hr@ORCL> commit;
  63. Commit complete.
  64. –trc摘入如下:
  65. Extent Control Header
  66. —————————————————————–
  67. Extent Header:: spare1: 0      spare2: 0      #extents: 2      #blocks: 16
  68. last map  0x00000000  #maps: 0      offset: 2716
  69. Highwater::  0x01000a13  ext#: 1      blk#: 2      ext size: 8
  70. #blocks in seg. hdr’s freelists: 0
  71. #blocks below: 10
  72. mapblk  0x00000000  offset: 1
  73. Disk Lock:: Locked by xid:  0x0006.012.0000018d
  74. ——————————————————–
  75. Low HighWater Mark :
  76. Highwater::  0x01000a13  ext#: 1      blk#: 2      ext size: 8
  77. –高水位点变为 0x01000a13 ,也就是2579块
  78. –接下来是回滚,回滚则将保持高水位点不变,也就是在2579块
  79. hr@ORCL> insert /*+ append */ into b select id+12,name from a;
  80. 4 rows created.
  81. hr@ORCL> rollback;
  82. Rollback complete.
  83. hr@ORCL> alter system dump datafile 4 block 2571;
  84. System altered.
  85. –trc文件摘入如下:
  86. Extent Control Header
  87. —————————————————————–
  88. Extent Header:: spare1: 0      spare2: 0      #extents: 2      #blocks: 16
  89. last map  0x00000000  #maps: 0      offset: 2716
  90. Highwater::  0x01000a13  ext#: 1      blk#: 2      ext size: 8
  91. #blocks in seg. hdr’s freelists: 0
  92. #blocks below: 10
  93. mapblk  0x00000000  offset: 1
  94. Unlocked
  95. ——————————————————–
  96. Low HighWater Mark :
  97. Highwater::  0x01000a13  ext#: 1      blk#: 2      ext size: 8
  98. –0x01000a13,也就是2579块,rollback,高水位点没有变化

在执行直接路径加载的过程中,高水位并没有真正提高,只有在事务提交后才会完成这个动作,在所有维护工作完成之后表才可以被访问
       所以,在提交之前如果想查询这张表是不被允许的,同理可知对表的增删改以及merge操作也是不被允许的

㈢ 直接路径加载与index
       
       直接路径插入时,不产生表块的回滚信息,而是依赖高水位点实现回滚
       但是,如果表有索引,将会产生索引的回滚信息,而且索引的块会被读进buffer cache 
       测试:

  1. –为b表创建一个索引
  2. hr@ORCL> create index idx_b on b (id);
  3. Index created.
  4. hr@ORCL> select file#,block# from v$bh where objd=(select data_object_id from user_objects where object_name=’IDX_B’);
  5. FILE#     BLOCK#
  6. ———- ———-
  7. 4       2587   ←← 段头块
  8. 4       2585   ←← L1块
  9. 4       2588   ←← 第一个索引数据块
  10. 4       2586   ←← L2块
  11. –重启数据库,清空buffer cache
  12. hr@ORCL> select file#,block# from v$bh where objd=(select data_object_id from user_objects where object_name=’IDX_B’);
  13. no rows selected
  14. hr@ORCL> insert /*+ append */ into b select * from a;
  15. 4 rows created.
  16. hr@ORCL> select file#,block# from v$bh where objd=(select data_object_id from user_objects where object_name=’IDX_B’);
  17. FILE#     BLOCK#
  18. ———- ———-
  19. 4       2588
  20. –直接路径插入时,索引块仍然会被调入buffer cache
  21. hr@ORCL> select xidusn,xidslot,xidsqn,ubafil,ubablk,ubasqn from v$transaction;
  22. XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK     UBASQN
  23. ———- ———- ———- ———- ———- ———-
  24. 6         41        399          2       1456        261
  25. –并且,对于索引块的修改,将会产生回滚信息,回滚信息保存在回滚块1456处
  26. –因此,索引并不会”直接路径插入”
  27. –因此,插入的索引数据,应该是在高水位点下:
  28. hr@ORCL>  select header_file,header_block from dba_segments where segment_name=’IDX_B’;
  29. HEADER_FILE HEADER_BLOCK
  30. ———– ————
  31. 4         2587
  32. hr@ORCL> alter system dump datafile 4 block 2587;
  33. System altered.
  34. –trc文件摘入如下:
  35. Extent Control Header
  36. —————————————————————–
  37. Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 8
  38. last map  0x00000000  #maps: 0      offset: 2716
  39. Highwater::  0x01000a1d  ext#: 0      blk#: 4      ext size: 8
  40. #blocks in seg. hdr’s freelists: 0
  41. #blocks below: 1
  42. mapblk  0x00000000  offset: 0
  43. Unlocked
  44. ——————————————————–
  45. Low HighWater Mark :
  46. Highwater::  0x01000a1d  ext#: 0      blk#: 4      ext size: 8
  47. –高水位点在2589块处,插入的索引数据在2588处,在高水位点下

Oracle官方文档建议,如果使用直接路径插入,向表中传送大量数据,可先将表上的索引删掉,插入结束后,再重新建立索引

㈣ 直接路径加载和一些限制
       
       使用直接路径加载方法时需要注意的地方如下:
       1)直接路径加载方法不是所有插入方式都支持的,最常见的带有value子句的insert语句就不支持
       2)该技术最常用在insert into … select …结构的插入语句中
       3)在使用直接路径加载技术插入数据直到事务提交,其他的增、删、改、查和merge操作是被禁止的
       4)因为是直接路径加载,所以高水位以下的空闲数据库块将不被使用,可能会因此导致数据段无限扩张
       5)当被操作的表上存在insert触发器、外键、IOT、表使用到了聚簇技术以及表中包含LOB字段时
            直接路径加载技术是无效的,此时将会自动的转变为常规插入

㈤ 小结
          
          使用直接路径加载技术之所以能提高性能是因为,该方法可以保证在加载数据的过程中最大限度的减少回滚数据的生成
          expdp/impdp不支持直接路径,而sqlldr支持(由参数direct=true指定,并且同时指定parallel=true,速度将会更快)
          如果我们在权衡利弊成本之后能最大化该方法,提高加载速度是必然的!

本文转自:http://blog.csdn.net/dba_waterbin/article/details/8607016

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,983
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,500
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,344
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,127
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,762
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,838