数日間グーグルでサーフィンした後、削除後にテーブルスペースの空きスペースを取り戻すための最もシンプルで明確な例を見つけました。これが役に立てば幸い
リンク:http : //www.dbforums.com/oracle/976248-how-reduce-tablespaces-used-space-after-delete-records-2.html
解決:
ALTER TABLE MOVE demo
それぞれが約1kサイズの9999行のテーブルを作成してみましょう。
SQL> create table t (x char(1000) default 'x' primary key);
Table created.
SQL> insert /*+ append nologging */ into t(x) select rownum from all_objects where rownum < 10000;
9999 rows created.
SQL> commit;
Commit complete.
テーブルには29のエクステントが割り当てられており、合計1460万です。
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
すべての行を削除してみましょう:
SQL> delete from t;
9999 rows deleted.
SQL> commit;
Commit complete.
Now- "surprise"-テーブルは今でも同じエクステントを使用しています:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
どうして ?テーブルのすべての行を削除しても、ハイウォーターマークは減少せず、最大の同時実行性を可能にするために減少することはありません(Oracleは同時実行性の最大化、つまりパフォーマンスとスケーラビリティについて真剣に取り組んでいます。これが成功の主な理由です。エンタープライズアプリケーション)。
未使用のスペース(HWMの上にあるスペース)の割り当てを解除してもあまり効果はありません(HWMの上に未使用のスペースが多くないため)。
SQL> alter table t deallocate unused;
Table altered.
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 13959168
次に、テーブルを移動します。これは、本質的にはテーブルのクローン(トリガー、制約などを含む)、行を転送し、「古い」テーブルを削除して新しい名前を変更することを意味します。すべてカーネルによって作成されているため、非常に安全ですマシン/サーバーに障害が発生した場合でも:
SQL> alter table t move;
Table altered.
これで、最初のエクステントのみが割り当てられました。
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
1 65536
警告:通常、テーブルのインデックスの多く/すべてが移動後に使用できなくなることがあります(この場合ではなく、最新のリリースである9.2.0.4を実行しています。これにより、テーブルが完全に空の場合にプロセスが最適化されます。 ):
SQL> col table_name form a30
SQL> col index_name form a30
SQL> set lines 123
SQL> select table_name, index_name, status from user_indexes where table_name='T';
TABLE_NAME INDEX_NAME STATUS
------------------------------ ------------------------------ ------------------------
T SYS_C002573 VALID
STATUSが有効でない場合は、手動でインデックスを再構築できます。
SQL> alter index SYS_C002573 rebuild;
Index altered.
または、プロセス全体を自動化することもできます。
set serveroutput on size 100000
begin
for n in (select index_name from user_indexes where status <> 'VALID') loop
dbms_output.put_line ('rebuilding ' || n.index_name);
execute immediate 'alter index ' || n.index_name || ' rebuild';
end loop;
end;
/
例として、手動でインデックスをUNUSABLEに設定してみましょう。
SQL> alter index SYS_C002573 unusable;
Index altered.
SQL> set serveroutput on size 100000
SQL> begin
2 for n in (select index_name from user_indexes where status <> 'VALID') loop
3 dbms_output.put_line ('rebuilding ' || n.index_name);
4 execute immediate 'alter index ' || n.index_name || ' rebuild';
5 end loop;
6 end;
7 /
rebuilding SYS_C002573
PL/SQL procedure successfully completed.
HTHアルベルト