Dopo aver navigato su Google per giorni, ho trovato l'esempio più semplice e chiaro per recuperare lo spazio libero nel tablespace dopo l'eliminazione. spero che questo possa essere d'aiuto
Link: http://www.dbforums.com/oracle/976248-how-reduce-tablespaces-used-space-after-delete-records-2.html
soluzione:
ALTER TABLE MOVE demo
Creiamo una tabella con 9999 righe al suo interno, ciascuna delle dimensioni intorno a 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.
La tabella ha 29 estensioni assegnate ad essa, per un totale di 14,6 milioni:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
Eliminiamo TUTTE le righe:
SQL> delete from t;
9999 rows deleted.
SQL> commit;
Commit complete.
Ora "sorpresa" - la tabella usa ancora le stesse estensioni:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
Perché ? Perché anche se si eliminano tutte le righe della tabella, l'High Water Mark non viene diminuito, non viene mai diminuito, per consentire la massima concorrenza (Oracle è seriamente intenzionato a massimizzare la concorrenza, ovvero prestazioni e scalabilità; è la ragione principale del suo successo nelle applicazioni Enterprise).
La deallocazione dello spazio inutilizzato (= spazio sopra l'HWM) non aiuta molto (poiché non c'è molto spazio inutilizzato sopra l'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
Muoviamo ora la tabella, che in sostanza significa clonare la tabella (inclusi trigger, vincoli e così via), trasferire le righe, eliminare la "vecchia" tabella e rinominare la nuova - tutto creato dal kernel, così super-sicuro anche in caso di guasto macchina / server:
SQL> alter table t move;
Table altered.
Ora, abbiamo ora solo l'estensione iniziale assegnata:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
1 65536
Avvertenza: in genere accade che molti / tutti gli indici sulla tabella siano INUTILIZZABILI dopo lo spostamento (non in questo caso ma sto eseguendo 9.2.0.4, l'ultima versione, che probabilmente ha ottimizzato il processo in caso di tabelle totalmente vuote ):
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
Se STATUS non fosse VALID, potresti semplicemente ricostruire manualmente gli indici:
SQL> alter index SYS_C002573 rebuild;
Index altered.
Oppure potresti automatizzare l'intero processo:
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;
/
Ad esempio, impostiamo manualmente l'indice su 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.
HT Alberto