peibaishi 发表于 2018-9-14 07:30:54

浅谈Oracle的高水位线--HWM

  高水位是记录段里能容纳数据的上限,高水位存在段里
  全表扫先读段头块,而后在段头块里面找到HWM
  下面用实验由内而外来理解Oracle的HWM
  --t表有一条数据
  hr@ORCL> select * from t;

  >  ---------- ----------
  1 AAAAA
  --找t段的段头块
  hr@ORCL> select header_file,header_block from dba_segments where segment_name='T' and owner='HR';
  HEADER_FILE HEADER_BLOCK
  ----------- ------------
  4   387
  --另开一个session,dump段头块

  sys@ORCL>>
  Session>
  sys@ORCL>>
  System>  dump的部分trc内容摘入
  Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0   spare2: 0   #extents: 1   #blocks: 8
  last map 0x00000000 #maps: 0   offset: 2716

  Highwater:: 0x01000189 ext#: 0   blk#: 8   ext>  #blocks in seg. hdr's freelists: 0
  #blocks below: 5
  mapblk 0x00000000 offset: 0
  Unlocked
  --------------------------------------------------------
  Low HighWater Mark :

  Highwater:: 0x01000189 ext#: 0   blk#: 8   ext>  #blocks in seg. hdr's freelists: 0
  #blocks below: 5
  mapblk 0x00000000 offset: 0
  Level 1 BMB for High HWM block: 0x01000181
  Level 1 BMB for Low HWM block: 0x01000181
  --------------------------------------------------------
  Segment Type: 1 nl2: 1   blksz: 8192fbsz: 0
  L2 Array start offset: 0x00001434
  First Level 3 BMB: 0x00000000
  L2 Hint for inserts: 0x01000182
  Last Level 1 BMB: 0x01000181
  Last Level II BMB: 0x01000182
  Last Level III BMB: 0x00000000
  Map Header:: next 0x00000000 #extents: 1obj#: 52713 flag: 0x10000000
  Inc # 0
  Extent Map
  -----------------------------------------------------------------
  0x01000181 length: 8
  Auxillary Map
  --------------------------------------------------------
  Extent 0   : L1 dba: 0x01000181 Data dba: 0x01000184
  --------------------------------------------------------
  Second Level Bitmap block DBAs
  --------------------------------------------------------
  DBA 1:0x01000182
  d dump data blocks tsn: 4 file#: 4 minblk 387 maxblk 387
  --对t表做一次全表扫
  hr@ORCL> set autot traceonly
  hr@ORCL> select * from t;
  Execution Plan
  ----------------------------------------------------------
  Plan hash value: 1601196873
  --------------------------------------------------------------------------

  |>  --------------------------------------------------------------------------
  |0 | SELECT STATEMENT |   |   1 |20 |   3(0)| 00:00:01 |
  |1 | TABLE ACCESS FULL| T|   1 |20 |   3(0)| 00:00:01 |
  --------------------------------------------------------------------------
  Note
  -----
  - dynamic sampling used for this statement
  Statistics
  ----------------------------------------------------------
  0 recursive calls
  0 db block gets
  7 consistent gets--全表扫读了6个块
  0 physical reads

  0 redo>  469 bytes sent via SQL*Net to client
  385 bytes received via SQL*Net from client
  2 SQL*Net roundtrips to/from client
  0 sorts (memory)
  0 sorts (disk)
  1 rows processed
  这6个块是如何算出来的呢?
  hr@ORCL> select file_id,block_id,blocks from dba_extents where segment_name='T';
  FILE_IDBLOCK_ID   BLOCKS
  ---------- ---------- ----------
  4    385   8
  这t段一共用了8个块,分别是385 386 387 388 389 390 391 392 393
  Highwater:: 0x01000189 即:4号文件的393号块
  这个可由下面dbms_utility包算出
  sys@ORCL> select to_number('01000189','xxxxxxxx') from dual;
  TO_NUMBER('01000189','XXXXXXXX')
  --------------------------------
  16777609
  sys@ORCL> select dbms_utility.data_block_address_file(16777609) from dual;
  DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(16777609)
  ----------------------------------------------
  4
  sys@ORCL> select dbms_utility.data_block_address_block(16777609) from dual;
  DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(16777609)
  -----------------------------------------------
  393
  读了一次段头块:4号文件387号块
  读了高水位之下的388 389 390 391 392 等5个块
  这样一共就读了6个块
  注:
  385是FIRST LEVEL BITMAP BLOCK
  386是SECOND LEVEL BITMAP BLOCK
  接着分析我们所dump的内容:
  Low HighWater Mark :

  Highwater:: 0x01000189 ext#: 0   blk#: 8   ext>  接下来谈谈highwater mark 和 low highwater mark
  low high water mark与high water mark 之间可能存在formated block也可以可能存在unformatted block
  先来理清dba_tables里面的字段blocks的含义
  dba_tables.blocks记录的是分析得到的 formatted block 的总数
  而 low hwm 和 high hwm之间可能同时存在 formatted block 和 unfomatted block
  所以准确地说 blocks 不能代表 low hwm 或high hwm
  如果 low hwm 和 high hwm之间正好没有formatted block时,dba_tables.blocks和low hwm下的blocks一致
  那么什么是Oracle中未格式化的块呢?
  未格式化,意思就是这个块,已经是属于这个段了,但是还保留着原来的样子没动
  格式化就是把块中的数据清除掉,并把块头改为这个对象的
  MSSM表空间中的段,只有一个高水位,高水位下的块都是格式化了的
  但是ASSM表空间中的段,有两个高水位:低高水位和高高水位
  即上文trc里的:Highwater:: 0x01000189和Low HighWater Mark Highwater:: 0x01000189
  低高水位下的块全部是格式化了的
  但是低高水位和高高水位之间的块,则可能是格式化了的,也可能是没有
  现在的t的高高水位是file 4,block 393;其低高水位是file 4,block 393
  我们现在再来看一下t现在data_object_id是多少:
  hr@ORCL> select object_id,data_object_id from dba_objects where object_name='T';
  OBJECT_ID DATA_OBJECT_ID
  ---------- --------------
  52713   52714
  这里很明显t的data_object_id大于object_id
  也就是说,在t上曾经发生过move或truncate操作
  注意,对于truncate操作而言,truncate后其data_object_id不一定就是在原先的data_object_id上加1
  sys@ORCL> select to_char('52714','XXXXXXXX') from dual;
  TO_CHAR('
  ---------
  CDEA
  换句话说,t中现在在其低高水位和其高高水位之间的block,只要这个block上记录的data_object_id不等于CDEA
  我们可以通过dump里面的Block header dump部分中的seg/obj来判断其data_object_id是否与段编号相等
  那么这个block 就是一个未格式化的块
  也就是说,可以通过data_object_id来确定块是在HWM和LHWM的位置
  那么Oracle为什么要增加低高水位设置?出于什么目的?全表扫描时,是到低高水位,还是到高高水位?
  Oracle设计有一个原则,就是把一个大操作分散到很多小操作中,以保证某个大操作不会花费太长时间
  无论是延迟提交,还是什么,都体现了这种思想,这和Linux的理念有异曲同工之妙哦
  而低高水位线与高高水位线结合,正是这种思想的体现
  可以不用一次性格式化所有新分配的块,留一部分给下次操作来完成
  全表扫描时,通常都是读至低高水位线,然后根据位图去读低高与高高之间格式化过的块,避开未格式化的块
  如何查看HWM?如何知道HWM下有多少空闲的空间?
  最实用的方法就是dump segment_header,速度快,而且对应用没有影响
  而且,trc里面的"#blocks in seg. hdr's freelists:"可以告诉我们HWM下有多少空闲块
  这里需要注意,如果dba_segments.freelist_groups > 1,那么freelist不再segment header中
  比如,freelist_group = 3 ,则你便要分别dump header后面的3个块,来看每个group的freelist的个数
  那么如何降低HWM呢?
  ① expdp/impdp
  ② 10G及以后的版本可以采用shrink,需要注意的是,表所在表空间须为自动段空间管理

  >
  >  ③ 使用move,不过在Move期间,会影响到DML语句,如UPDATE,也需要考虑空间问题
  总之move会锁表 而且是TM 另外还会影响index,所以,之后记得rebuild index

  >
  >  ④ CTAS 然后rename,rebuild index
  ⑤ 在线重定义
  等等.......
  oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html

页: [1]
查看完整版本: 浅谈Oracle的高水位线--HWM