Если в таблице слишком много пустых блоков, то оптимизировать данные помогут следующие действия
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, не так ли?
И не стоит забывать, что в любом случае после выполнения подобных операций необходимо обновить статистику таблицы и связанных с ней индексов, дабы избежать деградации производительности.