Главная > SQL > Убрать пустые блоки из таблицы


Убрать пустые блоки из таблицы

Если в таблице слишком много пустых блоков, то оптимизировать данные помогут следующие действия

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;

Похожие записи:

Categories: SQL Tags: , , ,
  1. 2 Февраль 2013 в 13:13 | #1

    Существует более простой способ, автор:

    alter table owner.table_name shrink space cascade;

    Мы же работаем с современными версиями Oracle, не так ли?

    И не стоит забывать, что в любом случае после выполнения подобных операций необходимо обновить статистику таблицы и связанных с ней индексов, дабы избежать деградации производительности.

  1. Пока что нет уведомлений.