Oracle数据库表碎片整理
一、Oracle数据库表是否需要碎片整理,看个例子,有人是这么说的
由于oracle的数据表的存储不像mysql(innodb)那样使用的聚集组织表(IOT)存放数据,而是使用的是称为堆(HEAP)的方式来存放数据.
数据行被存放到的块是随机的.进行全表扫描的时候读取出来的数据行没有按一定的方式进行排序.所以ORACLE可以对任意有空闲空间的数据块进行数据插入.
也就是说空闲空间的数据块还会被使用,从这个意义上讲,是不需要碎片整理
SQL> exec dbms_stats.gather_table_stats('TDWCMSDB','TDWCMS_PRODUCT');
analyze table t1 compute statistics;
SQL> select table_name,num_rows,blocks,num_rows/blocks from dba_tables where table_name='TDWCMS_PRODUCT' and owner='TDWCMSDB';
TABLE_NAME NUM_ROWS BLOCKS NUM_ROWS/BLOCKS
------------------------------ ---------- ---------- ---------------
TDWCMS_PRODUCT 120380 4378 27.4965738
当前该表拥有120380行,4378个数据块,平均每个块大概是存放了27行数据.
在使用脚本随机删除2000行数据后, 平均每个块存放的行数 明显变小了,
然后在随机插入数据2000行后,平均每个块存放的行数 又回到了27行,也就是数据库块中的空闲空间被使用了。
看吧,这个例子说的空闲空间,其实指的是 “表段已经申请到的空间的重复使用",的而且不是真正的 “表空间的Free Space”。
二、碎片是如何产生的
空间结构关系:
表空间(Tablespace)、段(Segment)、范围(Extent)、自由空间(Free Space)、数据块(Data Block)
其中数据块包括:
Unformatted Blocks 已申请来未格式化的
Unused Blocks 已格式化未使用的
Used Blocks
部分已使用的
全部已使用的,已使用满的 Full Blocks
1.理论知识:
表在建立时(逻辑上的段),根据initial_extent参数来初始化范围(extent)表在建立时(逻辑上的段),根据initial_extent参数来初始化范围(extent),
在这些初始范围充满数据时,段会请求增加另一个范围。这样的扩展过程会一直继续下去,直到达到最大的范围值,或者在表空间中已经没有自由空间用于下一个范围。
最理想的状态就是一个段的数据可被存在单一的一个范围中。这样,所有的数据存储时靠近段内其它数据,并且寻找数据可少用一些指针。
但是一个段包含多个范围的情况是大量存在的,没有任何措施可以保证这些范围是相邻存储的,当要满足一个空间要求时,数据库不再合并相邻的自由范围(除非别无选择),
而是寻找表空间中最大的自由范围来使用。这样将逐渐形成越来越多的离散的、分隔的、较小的自由空间,即碎片。
2.碎片对系统的影响
碎片越来越多时,找到一个足够大的自由范围已变得越来越困难,导致系统性能减弱
SMON (系统监控)后台进程周期性地合并部分自由范围Extent(如表空间的 pctincrease 为非 0 ),但始终有一部分自由范围无法得以自动合并,浪费了大量的表空间
3.自由范围的碎片计算
自由范