On shrinking table sizes

本文演示了在Oracle数据库中如何通过删除记录并使用ALTER TABLE MOVE来重新整理表空间,释放未使用的空间,以及重建索引来优化存储效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Usually, this is a good thing because the 'deleted' space will be used for future insert statements. Also update statements that increase the data size can use such 'deleted' space. Technically, this is because Oracle does not move the high water mark downwards. However, when there is a mass delete operation that won't be followed by insert or update statements, it might be advisable to really free the deleted space. In order to demonstrate this, I create a table and insert 10000 records:
create table table_size_test (
  a char(100),
  b number
) storage (initial 65K  next 65K  pctincrease 0)
tablespace ts_01;

begin
  for i in 1 .. 10000 loop
    insert into table_size_test values
      (dbms_random.string('X', 100),i);
  end loop;
end;
/

commit;
I also create an index on the table:
create index ix_table_size_test on table_size_test(a)
  storage (initial 65K  next 65K  pctincrease 0)
  tablespace ts_02;
Let's see how much space the table and index use:
select substr(segment_name,1,20) segment, bytes / 1024 "Size [KB]" from user_segments
where segment_name in ('TABLE_SIZE_TEST', 'IX_TABLE_SIZE_TEST');
SEGMENT               Size [KB]
-------------------- ----------
TABLE_SIZE_TEST            1280
IX_TABLE_SIZE_TEST         1280
Half of the records in the table are deleted:
delete from table_size_test where mod(b,2)=0;

commit;
No space is freed:
select substr(segment_name,1,20) segment, bytes / 1024 "Size [KB]" from user_segments
where segment_name in ('TABLE_SIZE_TEST', 'IX_TABLE_SIZE_TEST');
SEGMENT               Size [KB]
-------------------- ----------
TABLE_SIZE_TEST            1280
IX_TABLE_SIZE_TEST         1280
Using alter table .. move defragments (if you want that expression) and stores the table more efficiently:
alter table table_size_test move;
select substr(segment_name,1,20) segment, bytes / 1024 "Size [KB]" from user_segments
where segment_name in ('TABLE_SIZE_TEST', 'IX_TABLE_SIZE_TEST');
SEGMENT               Size [KB]
-------------------- ----------
TABLE_SIZE_TEST             640
IX_TABLE_SIZE_TEST         1280
However, there are two problems. First, the size of the index is not reduced. But even worse: the index is invalidated!:
select status from user_indexes
where index_name = 'IX_TABLE_SIZE_TEST';
STATUS
--------
UNUSABLE
The index needs to be rebuilt:
alter index ix_table_size_test rebuild;
This not only validates the index again, but also shrinks its size:
select status, bytes/1024 from
  user_indexes join user_segments on
    index_name = segment_name
where index_name = 'IX_TABLE_SIZE_TEST';
STATUS   BYTES/1024
-------- ----------
VALID           704
Thus, using alter table move, the allocated size on the harddisk for table and index had been roughly decreased by 50%.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值