Setelah berselancar di Google selama berhari-hari, saya telah menemukan contoh paling sederhana dan jelas untuk mendapatkan kembali ruang kosong di tablespace setelah dihapus. saya harap ini membantu
Tautan: http://www.dbforums.com/oracle/976248-how-reduce-tablespaces-used-space-after-delete-records-2.html
larutan:
ALTER TABLE MOVE demo
Mari kita buat tabel dengan 9999 baris di dalamnya, masing-masing berukuran sekitar 1k:
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.
Tabel memiliki 29 luasan yang dialokasikan, dengan total 14,6 juta:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
Mari kita hapus SEMUA baris:
SQL> delete from t;
9999 rows deleted.
SQL> commit;
Commit complete.
Sekarang- "kejutan" - tabel masih menggunakan luasan yang sama:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
Mengapa Karena bahkan jika Anda menghapus semua baris tabel, Tanda Air Tinggi tidak berkurang - tidak pernah menurun, untuk memungkinkan konkurensi maksimum (Oracle sangat serius dalam memaksimalkan konkurensi yaitu kinerja dan skalabilitas; itu adalah alasan utama di balik keberhasilannya dalam aplikasi Perusahaan).
Deallocating ruang yang tidak digunakan (= ruang di atas HWM) tidak banyak membantu (karena tidak ada banyak ruang yang tidak digunakan di atas 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
Sekarang, mari kita PINDAHKAN tabel, yang pada dasarnya berarti mengkloning tabel (termasuk pemicu, kendala, dan sebagainya), mentransfer baris, menjatuhkan tabel "lama" dan mengganti nama yang baru - semua dibuat oleh kernel, sehingga sangat aman bahkan dalam kasus kegagalan mesin / server:
SQL> alter table t move;
Table altered.
Sekarang, kita sekarang hanya memiliki alokasi awal:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
1 65536
Peringatan: biasanya terjadi bahwa banyak / semua indeks di atas tabel tidak dapat digunakan setelah pindah (tidak dalam kasus ini tetapi saya menjalankan 9.2.0.4, rilis terbaru, yang mungkin telah mengoptimalkan proses jika tabel benar-benar kosong ):
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
Jika STATUS bukan VALID, Anda cukup membangun kembali secara manual indeks:
SQL> alter index SYS_C002573 rebuild;
Index altered.
Atau Anda dapat mengotomatiskan seluruh proses:
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;
/
Sebagai contoh, mari kita atur secara manual indeks ke 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 Alberto