3

如果这样做会释放超过 2gb 的表空间,我只想重建我的表索引。如何确定通过重建索引将释放的表空间量?

4

1 回答 1

2

您可以使用DBMS_SPACE.CREATE_INDEX_COST来估计重建索引后使用的空间量。从 DBA_SEGMENTS.BYTES 中减去它会给您估计节省的空间。

下面的示例显示 DBMS_SPACE 对重建异常糟糕的索引所节省的空间做出了相当准确的预测。该软件包需要收集统计信息,因此您可能想了解从这个 稍微相关的答案中收集统计信息引起的潜在问题。

首先,创建一个表和样本数据,并收集统计数据。

drop table test1 purge;
create table test1(a number, b number, c number);

insert /*+ append */ into test1 select level, level, level
from dual connect by level <= 500000;
commit;

begin
    dbms_stats.gather_table_stats(user, 'TEST1');
end;
/

这表明 DBMS_SPACE 对新索引的成本做出了准确的预测。

declare
    v_used_bytes number;
    v_alloc_bytes number;
begin
    dbms_space.create_index_cost(
        ddl => 'create index test1_idx on test1(a, b, c)'
        ,used_bytes => v_used_bytes
        ,alloc_bytes => v_alloc_bytes
    );
    dbms_output.put_line('Esimated Bytes: '||
        trim(to_char(v_alloc_bytes,'999,999,999')));
end;
/

Esimated Bytes: 14,680,064


create index test1_idx on test1(a, b, c);
select trim(to_char(bytes, '999,999,999')) actual_bytes
    from dba_segments where segment_name = 'TEST1_IDX';

ACTUAL_BYTES
------------
15,728,640

现在模拟一个“坏”的索引。一个常见的误解是索引不会自动重用空间。真正的问题是,在删除每个条目之前,索引不会为叶块重新声明空间。此示例删除了 95% 的行,但空间量相同。

delete from test1 where mod(a, 20) <> 1;
commit;
select trim(to_char(bytes, '999,999,999')) actual_bytes
    from dba_segments where segment_name = 'TEST1_IDX';

ACTUAL_BYTES
------------
15,728,640

重新收集统计数据,现在估计与重建后的实际大小非常相似。

begin
    dbms_stats.gather_table_stats(user, 'TEST1');
end;
/

declare
    v_used_bytes number;
    v_alloc_bytes number;
begin
    dbms_space.create_index_cost(
        ddl => 'create index test1_idx on test1(a, b, c)'
        ,used_bytes => v_used_bytes
        ,alloc_bytes => v_alloc_bytes
    );
    dbms_output.put_line('Esimated Bytes: '||
        trim(to_char(v_alloc_bytes,'999,999,999')));
end;
/

Esimated Bytes: 720,896


alter index test1_idx rebuild;
select trim(to_char(bytes, '999,999,999')) actual_bytes
    from dba_segments where segment_name = 'TEST1_IDX';

ACTUAL_BYTES
------------
851,968
于 2013-07-16T17:22:20.150 回答