2013-07-16 57 views

回答

2

您可以使用DBMS_SPACE.CREATE_INDEX_COST來估計索引重建後使用的空間量 。從DBA_SEGMENTS.BYTES中減去它可以估算節省的空間。

下面的示例顯示DBMS_SPACE對重建非常差的索引所節省的空間進行了相當準確的預測。包 需要收集統計信息,因此您可能需要閱讀有關從this 收集統計數據導致的潛在問題稍有相關的答案。

首先,創建一個表和示例數據,並收集統計信息。

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