Después de navegar en Google durante días, he encontrado el ejemplo más simple y claro para reclamar el espacio libre en el espacio de tabla después de eliminarlo. espero que esto ayude
Enlace: http://www.dbforums.com/oracle/976248-how-reduce-tablespaces-used-space-after-delete-records-2.html
solución:
ALTER TABLE MOVE demo
Creemos una tabla con 9999 filas, cada una de ellas con un tamaño de alrededor de 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 tabla tiene 29 extensiones asignadas, para un total de 14.6M:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
Eliminemos TODAS las filas:
SQL> delete from t;
9999 rows deleted.
SQL> commit;
Commit complete.
Ahora- "sorpresa" - la tabla todavía usa las mismas extensiones:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
29 14680064
Por qué ? Porque incluso si elimina todas las filas de la tabla, la High Water Mark no disminuye, nunca disminuye para permitir la máxima concurrencia (Oracle se toma muy en serio la maximización de la concurrencia, es decir, el rendimiento y la escalabilidad; es la razón principal de su éxito en aplicaciones empresariales).
Desasignar el espacio no utilizado (= espacio sobre el HWM) no ayuda mucho (ya que no hay mucho espacio no utilizado sobre el 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
Ahora, MOVEMOS la tabla, que en esencia significa clonar la tabla (incluidos los desencadenantes, restricciones, etc.), transferir las filas, soltar la tabla "antigua" y cambiar el nombre de la nueva, todo hecho por el núcleo, muy seguro incluso en caso de falla de la máquina / servidor:
SQL> alter table t move;
Table altered.
Ahora, solo tenemos la extensión inicial asignada:
SQL> select count(*), sum(bytes) from user_extents where segment_name='T';
COUNT(*) SUM(BYTES)
---------- ----------
1 65536
Advertencia: normalmente sucede que muchos / todos los índices de la tabla no se pueden usar después del movimiento (no en este caso, pero estoy ejecutando 9.2.0.4, la última versión, que probablemente ha optimizado el proceso en el caso de tablas totalmente vacías ):
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
Si STATUS no fuera VÁLIDO, simplemente podría reconstruir manualmente los índices:
SQL> alter index SYS_C002573 rebuild;
Index altered.
O podría automatizar todo el proceso:
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;
/
Como ejemplo, configuremos manualmente el índice como INUSABLE:
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