如果这样做会释放超过 2gb 的表空间,我只想重建我的表索引。如何确定通过重建索引将释放的表空间量?
问问题
267 次
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 回答