高水位线
HWM是一个标记,用来说明已经有多少数据块分配给这个segment。DBA_TABLES.BLOCKS即HWM。HWM通常增长的幅度为一次5个数据块,原则上HWM只会增大,不会缩小,即使将表中的数据全部删除,HWM还是为原值,由于这个特点,使HWM很象一个水库的历史最高水位,这也就是HWM的原始含义,当然不能说一个水库没水了,就说该水库的历史最高水位为0。但是如果我们在表上使用了truncate命令,则该表的HWM会被重新置为0。
a) 全表扫描通常要读出直到HWM标记的所有的属于该表数据库块,即使该表中没有任何数据。
b) 即使HWM以下有空闲的数据库块,键入在插入数据时使用了append关键字,则在插入时使用HWM以上的数据块,此时HWM会自动增大。如果插入数据时没有append关键字,则插入时会在HWM以内找空闲的块,这样HWM就不会增大
高水位线内的块分4种,一种是满了的块,一种没满的块,一种是extents扩展的空块,一种是删除数据后的空块
DBA_SEGMENTS.BLOCKS=DBA_TABLES.BLOCKS+ DBA_TABLES.EMPTY_BLOCKS
DBA_TABLES.EMPTY_BLOCKS 代表分配给该表,但是在高水位线以上的数据库块。因为每一次对表进行拓展都是以extent为单位的,所以会出现空数据块。
Delete操作的时候,dba_segments.Blocks、user\dba_tables.Blocks、 user\dba_tables.empty_blocks三者都不会减小
insert /*+append*/ into XXX values(XXX);
使用append提示进行insert时系统不去查找freelist链表中的空闲块,直接在高水标记位以上插入数据,因此速度比较快。但若是对于经常delete的表,浪费磁盘空间太大。
查找数据库中实际大小和分配的空间差别最大的表,查找脚本如下:
条件为什么block>100,因为一些很小的表,只有几行数据实际大小很小,但是block一次性分配就是5个,5个block相对于几行小表数据来说就相差太大了
算法中/0.9是因为块的pfree一般为10%,所以一个块最多只用了90%,而且一行数据大于8KB时容易产生行链接,把一行分片存储,一样的一个块连90%都用不满
AVG_ROW_LEN还是比较准的,比如个人实验情况一表6个字段,一个number,其他5个都是char(100)但是实际数据都是’1111111’7位,AVG_ROW_LEN显示依然为513
可收缩的空间本人习惯称呼它们为碎片
SELECT TABLE_NAME,(BLOCKS*8192/1024/1024)"理论大小M",
(NUM_ROWS*AVG_ROW_LEN/1024/1024/0.9)"实际大小M",
round((NUM_ROWS*AVG_ROW_LEN/1024/1024/0.9)/(BLOCKS*8192/1024/1024),3)*100||'%' "实际使用率%"
FROM USER_TABLES where blocks>100 and (NUM_ROWS*AVG_ROW_LEN/1024/1024/0.9)/(BLOCKS*8192/1024/1024)<0.3
order by (NUM_ROWS*AVG_ROW_LEN/1024/1024/0.9)/(BLOCKS*8192/1024/1024) desc
个人一般推荐alter table tablename move再alter index indexname rebuild不带online;系统不忙的话推荐alter table shrink space cascade;
实践中需要收缩表的情况:一张超大的表,你删除了80%以上的数据,就算立即收集了统计信息这张表的segments不变,该表对应的dba_data_files.file_name,dba_free_space.free大小不变,感觉dba_free_space.free虽然看起来不足,但是你仍可以继续insert 80%的数据到这张表,新增80%数据过程中segments、dba_data_files.file_name、dba_free_space.free还是不变。因为空块可以重用
当然,只有执行了表收缩,表的segments才能降下来,该表对应的dba_free_space.free会增加,dba_data_files.file_name占用的空间降低。
所以碎片其实就是空块和半空块。
实践中发现表收缩会产生很多REDO、UNDO、archvied log,比如执行alter table shrink space cascade
表收缩的方法
1. alter table tablename move [tablespace tablespacename]
1.1如果不指定表空间,就是在原表空间上move.需要额外一倍表大小空间,
1.2索引会失效,需要rebuild一下。
1.3不能在线进行,如果先执行dm操作没有commit,后再move则会直接报错;如果先move操作,期间可以执行select和平时一样正常速度返回数据,执行其他dml的话非常慢一直在等待move完成了才会真正开始执行。
2. alter table shrink space [ | compact | cascade ];
1.1必须开启行迁移功能(rowid 要发生变化)alter table table_name enable row movement; 注意:alter table XXX enable row movement语句会造成引用表XXX的对象(如存储过程、包、视图等)变为无效。执行完成后,最好执行一下utlrp.sql来编译无效的对象。
1.2表空间是auto管理方式
1.3不需要额外的空间
1.4可以在线进行,不管dml在前还是在后,也不管有没有commit, shrink也会正常执行完毕
1.5整理后,索引有效
alter table shrink space compcat;
收缩表,相当于把块中数据打结实了,但会保持 high water mark;
当系统的负载比较大时可以用
alter table shrink space;
收缩表,降低 high water mark;
alter table shrink space cascade;
收缩表,降低 high water mark,并且相关索引也会收缩一下,相当于rebulid index online
3. Truncate
4. expdp\impdp重新导出导入
表压缩和索引压缩
表压缩其实就是把表中重复的数据去掉,采用算法来替代这样重复的值
索引压缩其实就是把索引中重复的索引值去掉(表的字段值一样代表索引值一样,但是B树索引并不是说索引值后面对一大堆的rowid,而是一个索引值对应一个rowid,索引值是一样,但是rowid并不一样,索引索引块里面有很多记录行比如如下),采用算法来替代这样重复的值
索引值 rowid
5 1
5 8
5 13
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30126024/viewspace-2120235/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30126024/viewspace-2120235/