Etichettato: storage initial

Oracle, deframmentare e ricompattare tabelle, high watermark e initial extent

1.

Vi è mai capitato di svuotare una tabella contenente una mole abnorme di dati e poi scoprire che il tablespace è occupato tale e quale a prima? Le gioie dell’high watermark, cioè il livello più alto che è stato raggiunto dai dati contenuti nella tabella, che Oracle conserva gelosamente come una stima attendibile della dimensione probabile che raggiungeranno (e magari supereranno) detti dati. Di solito Oracle ha ragione, ma può capitare che un errore o un test portino il livello dell’acqua alta su ordini di grandezza che normalmente non sarebbero mai raggiunti.

Altrimenti, avete mai notato un anomalo peggioramento delle operazioni di I/O su una tabella neanche troppo grande, scoprendo poi che è dovuto alla sua frammentazione?

Azzerate l’high watermark e deframmentate la tabella spostandola da un tablespace all’altro (e, se serve, ritorno):

ALTER TABLE &TABLE_NAME MOVE TABLESPACE &TABLESPACE_NAME;

Idee per opzioni alternative si possono trovare ad esempio qui.

2.

Avete mai provato a importare il dump di una tabella vuota, ma che aveva una dimensione iniziale più grande di quanto disponibile nel tablespace in cui veniva importata (e perciò dava errore di importazione)? Oracle alloca per una tabella solo lo spazio che serve, ma se la tabella è stata creata con la clausola STORAGE (INITIAL […]) verrà allocata al minimo la dimensione indicata. Se cercate in giro, scoprite che modificare la dimensione iniziale della tabella non sembra tanto banale, e la (semplice) soluzione qui proposta viene proposta quasi con sufficienza, “ah, sì, be’, si può fare così”.

L’unica soluzione se ormai avete il dump e non potete rifarlo è dimensionare correttamente i tablespace di destinazione prima dell’importazione. Ma se avete modo di rifare l’export, e la dimensione specificata per la tabella è effettivamente sovradimensionata rispetto ai dati contenuti, un’opzione è cambiare la clausola STORAGE per la tabella (qui riporto la tabella nel tablespace iniziale, ma potreste non volerlo):

ALTER TABLE TABELLA MOVE TABLESPACE TBLSP_TEMP;

ALTER TABLE TABELLA MOVE TABLESPACE TBLSP_ORIGINALE STORAGE (INITIAL 10M NEXT 1M);

Consigli generali

Bisogna specificare che l’operazione di spostamento di tablespace è abbastanza sicura, ma evitate di eseguirla su tabelle grosse in ambienti di produzione, poiché potrebbe interrompere ogni altra operazione sulla tabella per tempi non trascurabili.

Ovviamente dovrete verificare di avere sul tablespace destinatario abbastanza spazio da contenere la tabella da spostare, non solo per lo spazio effettivamente occupato dai dati (la cui stima è ricavabile da una semplice moltiplicazione, numero di righe*dimensione occupata da una riga) ma anche per l’INITIAL EXTENT impostato nella tabella: potreste avere una tabella vuota, ma se come INITIAL EXTENT ha 100M, allora occuperà 100 MB del vostro tablespace.

Lo spostamento di tablespace così come l’ho presentato non è possibile se nella tabella sono presenti campi LONG.

Va poi detto che lo spostamento di tablespace rende invalidi gli indici, il che potrebbe generare errori durante le query (invece che il loro semplice non utilizzo). Ricostruite tutti gli indici della tabella dopo averla spostata nel tablespace desiderato:
begin
for rst in (select INDEX_NAME, TABLESPACE_NAME from user_indexes where table_name='TABELLA' and index_type like '%NORMAL')
loop
execute immediate 'alter index ' || rst.INDEX_NAME || ' rebuild ' || rst.TABLESPACE_NAME || ' [STORAGE (INITIAL ... NEXT ...)] [SHRINK SPACE COMPACT]';
end loop;
end;
/

I più arditi potranno ovviamente sbatacchiare interi schemi di tabelle da un tablespace all’altro con elaborati blocchi di codice anonimo. Ma non fornirò loro la pistola: Oracle è un DBMS che va temuto e rispettato, ed è sempre meglio capire cosa si sta facendo prima di farlo.

Annunci