表的碎片和文件系统的碎片化的是不一样的,当随着在一个表上的DML的上
操作越来越多时,HWM之前可能有很多空闲空间,而在读取表时HWM以下的块都会被
读进来,这样会产生更多的IO,从而影响性能.只有在DDL操作才会进表的收缩,
1,建一个表,并放入一百万条记录;
create table abb (a int,c char(512));
declare
i int;
begin
for i in 1..100000 loop
insert into abb values(i,'asfsadf');
end loop;
end;
create index abb_indx on abb(a);
2,收集表的表信息,并查看表的空间使用情况
SQL> exec dbms_stats.gather_table_stats('SYS','ABB');
PL/SQL procedure successfully completed.
SQL> select table_name,round((blocks*8),2)/1024,round((avg_row_len*num_rows),2)/1024/1024
2 from dba_tables
3 where table_name='ABB';
TABLE_NAME ROUND((BLOCKS*8),2)/1024
------------------------------ ------------------------
ROUND((AVG_ROW_LEN*NUM_ROWS),2)/1024/1024
-----------------------------------------
ABB 60.109375
49.4003296
通过以上的结果看出,表现在大小为 60M,实际的使用空间为50M,
还有PCT为百分之十,再加上一些其他的开销,基本上实际空间和
使用的块大小相等;
3, 删除 一半的记录,这时我们发现实际的空间和HWM标记使用的块
大小相差很远了,这时候如果在读取表是会把HWM之下的块全部读
进来从而产生很多IO,结果竟然到了25M
SQL> delete from abb where a<50000;
49999 rows deleted.
exec dbms_stats.gather_table_stats('SYS','ABB');
SQL> select table_name,round((blocks*8),2)/1024,round((avg_row_len*num_rows),2)/1024/1024
2 from dba_tables
3 where table_name='ABB';
TABLE_NAME ROUND((BLOCKS*8),2)/1024
------------------------------ ------------------------
ROUND((AVG_ROW_LEN*NUM_ROWS),2)/1024/1024
-----------------------------------------
ABB 60.109375
24.7006588
4,可以通过以下办法来解决,1,使用表MOVE和索引重建,2,通过 create table XXX as select * from abb; 3,使用导出和导入表 ;在这里用MOVE的方法来解决;
SQL> alter table abb move;
Table altered.
SQL> alter index abb_indx rebuild;
Index altered.
exec dbms_stats.gather_table_stats('SYS','ABB');
SQL> select table_name,round((blocks*8),2)/1024,round((avg_row_len*num_rows),2)/1024/1024
2 from dba_tables
3 where table_name='ABB';
TABLE_NAME ROUND((BLOCKS*8),2)/1024
------------------------------ ------------------------
ROUND((AVG_ROW_LEN*NUM_ROWS),2)/1024/1024
-----------------------------------------
ABB 30.0546875
24.7006588
现在HWM以下的块的实际使用的大小基本相等,表不存在碎片;
阅读(5022) | 评论(2) | 转发(1) |