今天下午好好看了oracle中的HWM,也就是高水位线,高水位线是一个段内使用和未使用的数据块的分界线。
Select * from user_tables where table_name=’TEST03’
其中有blocks,empty_blocks,num_rows其中的blocks也就是此表所占用的block数量,empty_blocks空的block,num_rows数据行数。User_tables中blocks也就是HWM
User_segment数据字典视图:blocks就是此segment分配的blocks总数,header_block就是此段断头所在的数据块编号等。
HWM的信息存储在段头中,根据段空间自动管理中是用位图来管理段内的空间分配
Delete,truncate和drop和高水位线的关系
Delete:
delete只是把删除了高水位线下的block内的数据,但是不会降低高水位线,空闲的数据块供以后数据插入使用,delete也不会回收表段的数据扩展,delete所作的只是更新了block的内的数据块,不会对segment的HWM,extent改变。
Truncate:
truncate table test02 drop storage 截断表,重置HWM,回收unused的block到tablespace中去供其余的对象使用
truncate的实质是:
truncate是新建一个segment然后与现有对象关联, truncate table tablename drop torage后segment中会新建segment,重构的initial大小的段,但是initial不一定是一个扩展的大小,很有可能是多个extent组成了initial段的大小。create table storage(initial 6M),此时oracle会为表段分配初始段initial大小6M,很有可能就是由多个extent组成的!
Truncate和flashback:
早上truncate一个table 然后flashck出错
flashback table test01 to timestamp to_timestamp('2011-9-13 17:00:00','yyyy-mm-dd hh24:mi:ss')
如果对table进行ddl操作,例如truncate然后再flashback,因为flashback利用的是放置在undo tablespace的回滚段,truncate是ddl没有走回滚段,所以无法闪回表,也就会报上述的表的定义已经更改,所以truncate也叫截断表,改变了表的“内部的一些东西”。
表内部零散blocks和truncate:
整理表内部的碎片,可以用truncate跟上reuse storage,重新导入/插入数据,由于重置了新的segment,所以也可以解决段的内部零散blocks。
Drop:
drop是直接删除数据字典中的表的信息,当然也不存在段的任何信息,HWM也就没有必要再提了。
(一般如果drop大的表时,先truncate然后再drop)
降低段的HWM:
alter table test02 move会将hwm移动,但是在move时需要双倍的表空间,如果表上有索引需要alter index indexname rebuild
alter table test02 shrink space收缩表 降低HWM
alter table test02 shrink space compact收缩表,但是不会降低HWM
(还可以利用exp和imp到segment中去来改变HWM,觉得可以新建segment然后exp,imp到新的segment来改变HWM,是否其中还有别的方法。)
回收段内的unused数据扩展但是并不能降低HWM:
使用alter table test02 deallocate unused会回收unused状态的extents,也就是会回收segment中高水位线以上的数据块,但是并不能改变segment中的高水位线。
HWM和全表扫描:
oracle的全表扫描是读取高水位线HWM一下的所有block,当用户直接路径插入行时,直接用append提示插入或sqlldr插入,数据块直接置于HWM之上,不再使用extents中得unused block。
直接插入和HWM
insert /*+append*/ into test01 values(1,'am')
(使用append 而且alter table tablename nologging模式会大量减少日志,只产生少数undo,append减少了空间的搜索,产生redo减少) 所以append方式会比平常的insert快,这里具体redo undo后续还要实际实验。
新Segment和HWM:
create table test03 select * from test01 where 1<>1
即使此时test03中没有任何数据,但是oracle中还是分配一个extent也就是8 blocks给此段,刚好db_block_size是8K的也就是64K给此表段,此高水位线blocks是0,然后后续的dml操作会增加HWM,如果没有shrink,move等操作,一般HWM都只会往上增,不会减少。