Sem dúvida, vc PODE remover o espaço acima da hwm, vc PODE também alterar pctfree/pctused pra que MENOS espaço dentro dos blocos fique reservado para futuros UPDATEs, vc PODE compactar tabelas e índices, vc PODE recriar um extent com um tamanho menor para que o último extent não usado até o fim seja menor, sim, como eu havia dito... Porém, via de regra, a quota do leão de espaço "desperdiçado" é o espaço ABAIXO da hwm que ficou em branco após DELETEs : como eu disse, esse espaço NÂO está desperdiçado pro si só, está reservado para futuros INSERTs/UPDATEs, mas se a pessoa SOUBER que aconteceram DELETEs em massa e não virão mais INSERTs/UPDATEs, aí sim, essa alocação passa a ser questionável.... Desse jeito : => primeiro, vamos criar uma tabespace LMT com extent sizes restritos E com controle de espaço dentro dos blocos automático, pra não precisarmos se preocupar com isso : SYSTEM@O11GR2>create tablespace TS_LMT_AUTO_FULL datafile 'C:\APP\ORACLE\ORADATA\O11GR2\O11GR2\TS_LMT_AUTO_FULL_01.DBF' size 100M autoextend on maxsize unlimited EXTENT MANAGEMENT LOCAL AUTOALLOCATE SEGMENT SPACE MANAGEMENT AUTO;
Tablespace criado. SYSTEM@O11GR2>alter user scott quota unlimited on TS_LMT_AUTO_FULL; Usuário alterado. => crio uma tabela com mais do que um punhado de extents : SCOTT@O11GR2>create table TAB_TESTE_ESPACO( c1 number, c2 varchar2(2000)) tablespace TS_LMT_AUTO_FULL; Tabela criada. SCOTT@O11GR2>create sequence SEQ_TESTe_ESPACO; Sequência criada. SCOTT@O11GR2>insert into TAB_TESTE_ESPACO (select seq_teste_espaco.nextval, lpad(object_name, 2000, '*') from all_objects); 68267 linhas criadas. SCOTT@O11GR2>commit; Commit concluído. SCOTT@O11GR2>select count(*) from TAB_TESTE_ESPACO; COUNT(*) ---------- 68267 1 linha selecionada. SCOTT@O11GR2> ==> Veja que cada extent está 'grudado' um no outro, o próximo começa onde o anterior terminou, não há 'GAPS' entre eles : SYSTEM@O11GR2>select owner, file_id, extent_id, block_id, bytes, block_id+blocks as PROXIMO from dba_extents where tablespace_name='TS_LMT_AUTO_FULL'; OWNER FILE_ID EXTENT_ID BLOCK_ID BYTES PROXIMO ---------------- ---------- ---------- ---------- ---------- --------------- SCOTT 5 0 128 65536 136 SCOTT 5 1 136 65536 144 SCOTT 5 2 144 65536 152 SCOTT 5 3 152 65536 160 SCOTT 5 4 160 65536 168 SCOTT 5 5 168 65536 176 SCOTT 5 6 176 65536 184 SCOTT 5 7 184 65536 192 SCOTT 5 8 192 65536 200 SCOTT 5 9 200 65536 208 SCOTT 5 10 208 65536 216 SCOTT 5 11 216 65536 224 SCOTT 5 12 224 65536 232 SCOTT 5 13 232 65536 240 SCOTT 5 14 240 65536 248 SCOTT 5 15 248 65536 256 SCOTT 5 16 256 1048576 384 SCOTT 5 17 384 1048576 512 .... vários e vários mais .... SCOTT 5 78 8192 1048576 8320 SCOTT 5 79 8320 8388608 9344 SCOTT 5 80 9344 8388608 10368 SCOTT 5 81 10368 8388608 11392 SCOTT 5 82 11392 8388608 12416 SCOTT 5 83 12416 8388608 13440 SCOTT 5 84 13440 8388608 14464 SCOTT 5 85 14464 8388608 15488 SCOTT 5 86 15488 8388608 16512 SCOTT 5 87 16512 8388608 17536 SCOTT 5 88 17536 8388608 18560 SCOTT 5 89 18560 8388608 19584 SCOTT 5 90 19584 8388608 20608 SCOTT 5 91 20608 8388608 21632 SCOTT 5 92 21632 8388608 22656 SCOTT 5 93 22656 8388608 23680 94 linhas selecionadas. => ok, consumiu quase 200 MB para armazenar as 68 mil e tantas linhas : SYSTEM@O11GR2>select sum(bytes), count(*) from DBA_EXTENTS where segment_name='TAB_TESTE_ESPACO'; SUM(BYTES) COUNT(*) ------------------------ ---------- 192.937.984 94 1 linha selecionada. SYSTEM@O11GR2> ==> no caso, meu blocksize é de 8KB, então com um registro lógico de pouco mais de 2000 caracteres , vou ter 3 linhas por bloco (considerando que além das linhas da tabela há Cabeçalhos e info interna que também vai nos blocos)... E como tablespaces LMT tem um bitmap no começo, veja acima que não começou a usar o espaço a partir do primeiro bloco da tablespace.... Muito bem, quero apagar dados de uma tal forma que fique um 'espaço em branco' mais ou menos entre o 10º e o 50º extent, o que implica em apagar dados com C1 entre SCOTT@O11GR2>select min(c1), max (c1) from (select c1, dbms_rowid.rowid_block_number(rowid) bloco_onde_a_linha_esta from TAB_TESTE_ESPACO) where bloco_onde_a_linha_esta between 208 and 4608; MIN(C1) MAX(C1) ---------- ---------- 220 13206 1 linha selecionada. SCOTT@O11GR2>delete from TAB_TESTE_ESPACO where c1 between 220 and 13206; 12987 linhas deletadas. SCOTT@O11GR2>commit; Commit concluído. SCOTT@O11GR2> ===> olha só como ficamos depois do DELETE : SYSTEM@O11GR2>select sum(bytes), count(*) from DBA_EXTENTS where segment_name='TAB_TESTE_ESPACO'; SUM(BYTES) COUNT(*) ------------------------ ---------- 192.937.984 94 1 linha selecionada. SYSTEM@O11GR2>select count(*) from scott.tab_teste_espaco; COUNT(*) ---------- 55280 1 linha selecionada. SYSTEM@O11GR2> ==> ó dia, ó azar, ó vida : continuo gastando o MESMO ESPAÇO que gastava antes pra armazenar 68267, o que aconteceu com o espaço que foi logicamente liberado após deletar as 12987 linhas ??? É o que eu disse, ele está em branco, sem dados, MAS AINDA ESTÁ RESERVADO pra uso dos futuros INSERTs/UPDATEs que vierem a acontecer na tabela , okdoc ?? E esse espaço está ABAIXO DA HWM, pois os DELETEs liberaram blocos ABAIXO da HWM : SYSTEM@O11GR2>SELECT file_name, hwm, blocks total_blocks, blocks-hwm+1 as Shrinkage_Available 2 FROM dba_data_files a, 3 ( select file_id, max(block_id+blocks) hwm 4 from dba_extents 5 group by file_id ) b 6 WHERE a.file_id = b.file_id 7* AND a.file_name='C:\APP\ORACLE\ORADATA\O11GR2\O11GR2\TS_LMT_AUTO_FULL_01.DBF'; FILE_NAME HWM TOTAL_BLOCKS SHRINKAGE_AVAILABLE -------------------------------------------------------------------- ---------- ------------ ------------------- C:\APP\ORACLE\ORADATA\O11GR2\O11GR2\TS_LMT_AUTO_FULL_01.DBF 23680 24864 1185 1 linha selecionada. ==>> ESTE é o caso que eu queria demonstrar : há um PEDAÇÂO de espaço que em tese PODE ser liberado pro sistema operacional mas está ABAIXO da hwm, blz ? []s Chiappa