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

[经验分享] 浅谈Oracle的高水位线--HWM

[复制链接]

尚未签到

发表于 2016-7-29 06:58:55 | 显示全部楼层 |阅读模式
   水位是记录段里能容纳数据的上限,高水位存在段里
     全表扫先读段头块,而后在段头块里面找到HWM
      下面用实验由内而外来理解Oracle的HWM
  

--t表有一条数据
hr@ORCL> select * from t;
ID NAME
---------- ----------
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> alter session set tracefile_identifier='sys_dump_t_01';
Session altered.
sys@ORCL> alter system dump datafile 4 block 387;
System altered.

   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 size: 8   --Highwater就是高水位,0x01000189这个是HWM的地址
#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 size: 8
#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: 8192   fbsz: 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: 1    obj#: 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
End 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
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   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 size
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_ID   BLOCK_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 size: 8


   接下来谈谈highwater mark 和 low highwater mark

   low high water mark与high water mark 之间可能存在formated block也可以可能存在unformatted block

  
DSC0000.png
     先来理清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,需要注意的是,表所在表空间须为自动段空间管理
     alter table tab_name enable row movement;
     alter table tab_name shrink space;
   ③ 使用move,不过在Move期间,会影响到DML语句,如UPDATE,也需要考虑空间问题
     总之move会锁表 而且是TM 另外还会影响index,所以,之后记得rebuild index
     alter table move tab_name; 在当前表空间中move
     alter table move tab_name tablespace tbs_name; 将其move到其他表空间
   ④ CTAS 然后rename,rebuild index
   ⑤ 在线重定义
  
      等等.......

运维网声明 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-250788-1-1.html 上篇帖子: oracle用expdp impdp导出导入 下篇帖子: Oracle Start with...Connect By子句
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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