Я бы хотел только перестроить индексы таблицы, если это приведет к выпуску табличного пространства более 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