Если в таблице слишком много пустых блоков, то оптимизировать данные помогут следующие действия
ALTER TABLE name_table MOVE;
ALTER INDEX name_index REBUILD;и не забыть обновить статистику для таблицы
begin
dbms_stats.gather_table_stats(schema,table);
end;
Список потенциальных таблиц с плохим распределением данных можно просмотреть так:
select * from
table(dbms_space.asa_recommendations('FALSE', 'FALSE', 'FALSE'))
order by reclaimable_space descПосмотреть данные по таблице, в том числе количество используемых блоков:
select BLOCKS, t.* from DBA_TAB_STATISTICS t where t.table_name = :name_tableили
select BLOCKS, t.* from dba_tables t where t.table_name = :name_table;Количество выделенных блоков:
select BLOCKS, t.* from dba_segments t where t.segment_name = :name_tableСкрипт для генерации шагов:
declare
l_table_name varchar2(30) := 'MTL_SYSTEM_ITEMS_B';
l_table_owner varchar2(30) := 'INV';
l_sql varchar2(4000);
begin
dbms_output.put_line('declare');
dbms_output.put_line(' l_cnt_block_before NUMBER;');
dbms_output.put_line(' l_cnt_block_after NUMBER;');
dbms_output.put_line('begin');
dbms_output.put_line(' select BLOCKS into l_cnt_block_before from dba_tab_statistics t where t.table_name = '''||l_table_name||''' and t.OWNER='''||l_table_owner||''';');
dbms_output.put_line(' dbms_output.put_line(''l_cnt_block_before=''||l_cnt_block_before);');
dbms_output.put_line(' --');
dbms_output.put_line(' execute immediate ''ALTER TABLE '||l_table_owner||'.'||l_table_name||' MOVE'';'||chr(10));
for idx_cur in (select t.OWNER,t.INDEX_NAME from all_indexes t where t.TABLE_OWNER = l_table_owner and t.TABLE_NAME = l_table_name order by t.INDEX_NAME)
loop
l_sql := 'ALTER INDEX '||idx_cur.OWNER||'.'||idx_cur.INDEX_NAME||' REBUILD';
dbms_output.put_line(' execute immediate '''||l_sql||''';');
end loop;
dbms_output.put_line(chr(10)||' fnd_stats.gather_table_stats( ownname => '''||l_table_owner ||''' , tabname => '''||l_table_name ||''', degree => 4 ); ');
dbms_output.put_line(' select BLOCKS into l_cnt_block_after from dba_tab_statistics t where t.table_name = '''||l_table_name||''' and t.OWNER='''||l_table_owner||''';');
dbms_output.put_line(' dbms_output.put_line(''l_cnt_block_after=''||l_cnt_block_after);');
dbms_output.put_line('end;');
end;
Альтернативный вариант борьбы с пустыми блоками
begin execute immediate 'alter table INV.MTL_SYSTEM_ITEMS_B enable row movement'; execute immediate 'lock table INV.MTL_SYSTEM_ITEMS_B in exclusive mode nowait'; execute immediate 'alter table INV.MTL_SYSTEM_ITEMS_B shrink space cascade'; commit; -- + exec rebild indexes, gather statistics end;

Существует более простой способ, автор:
alter table owner.table_name shrink space cascade;
Мы же работаем с современными версиями Oracle, не так ли?
И не стоит забывать, что в любом случае после выполнения подобных операций необходимо обновить статистику таблицы и связанных с ней индексов, дабы избежать деградации производительности.