Recuperare spazio dopo un import

giovedì 17 settembre 2009 alle 17:07 | Pubblicato su Installation and Configuration, Varie | 7 commenti
Tag:

Ieri, facendo operazioni di manutenzione su un database di sviluppo sono incappato in una situazione che non mi era mai capitata.  Dopo aver importato un dump (tramite data pump) di uno schema piuttosto voluminoso uno sviluppatore ha fatto un po’ di pulizia sui dati per “snellire lo schema” riducendo di molto il volume occupato dallo schema. Lo schema però stava su una tablespace ad esso dedicata appunto per la sua voluminosità, e quindi volevo “restringere” i file, ma naturamente non ero in grado di farlo. Infatti una volta che Oracle ha utilizzato un blocco in file quel blocco rimane marcato per sempre, ciò impedisce un restringimento dei datafile che interessi questi blocchi.

Essendo in ambiente di sviluppo ho deciso di fare qualche esperimento per cercare di recuperare spazio disco. Per prima cosa ho liberato lo spazio occupato da alcune tabelle, o meglio allocato ma non più usato, utilizzando il comando ALTER TABLE … SHRINK SPACE CASCADE; Poi  ho deciso di provare ad utilizzare l’Enterprise Manager ( o db console) per “riorganizzare” gli oggetti e poter finalmente restringere le tablespace. Come prima cosa ho trovato un baco (parliamo di un db 10.2.0.4 su win32) sulla db console; infatti sul tab “amministrazione” (purtroppo ho le voci in italiano) sotto la parte SCHEMA – oggetti database c’è il link “Riorganizza Oggetti”. Il primo passo di questa procedura è la scelta fra tre opzioni: Oggetti dello Schema, Schema, Tablespace. Ebbene, l’ultima opzione era quella più adatta al mio caso, peccato che la selezione della tablespace non funzioni.  Ho allora ripiegato sull’opzione “Schema”, ho pensato di spostare tutto su una nuova tablespace più piccola, ho seguito tutti i passi, però la procedura è fallita, per mancanza di spazio nella nuova tablepace. Mentre in partenza lo schema (dopo lo shrink) occupava circa un giga e mezzo, sulla destinazione aveva riempito 5 giga byte e non gli bastavano….

Ho quindi abbandonato la db console e ripreso il buon vecchio e caro SQL*Plus. A questo punto ho capito dove stava l’inghippo, infatti se io importo una schema con una tabella che occupa un giga byte, viene creato un segmento con la initial extent size pari alla dimensione della tabella. Se si fa lo shrink l’occupazione della tabella cala, ma se si fa una cosa tipo ALTER TABLE X MOVE TABLESPACE TBS2;  la tabella ritorna ad occupare un giga byte. Basta saperlo, infatti cambiando il comando di move in ALTER TABLE X MOVE TABLESPACE TBS2 STORAGE (INITIAL 5) si ovvia al problema.

Altro piccolo problema che ho incontrato è stato lo spostamento dei LOB. Infatti, generando uno script di rebuild degli indici fra gli altri mi sono trovato qualcosa di questo tipo:

SQL> @move_indexes
alter index SYS_IL0000060941C00004$$ rebuild tablespace fwsfa storage (initial 5)
*
ERROR at line 1:
ORA-02327: cannot create index on expression with datatype LOB

Io confesso non amo e non conosco molto i LOB, però ho capito che per ogni colonna LOB esiste un segmento di tipo LOBSEGMENT e uno di tipo LOBINDEX (questi compaiono evidentemente nella USER_INDEXES da dove ho generato lo script di rebuild).  Nel mio schema per fortuna c’erano solo tre colonne di tipo LOB, e quindi per ciascuna è stato sufficente utilizzare questo comando:

ALTER TABLE TAB1 MOVE LOB (COLUMNX) STORE AS [LOBSEGMENTNAME] (TABLESPACE TBS2);

In questo modo viene spostato sia il segmento LOBSEGMENT che il suo indice.

La prossima v0lta che dovro “raschiare” spazio su un database server sarò più preparato🙂

7 commenti »

RSS feed for comments on this post. TrackBack URI

  1. Potresti anche usare la sintassi…
    alter table t move lob(c) store as nuovo_nome (tablespace users);

    così da “nominare” il segmento e dargli un nome sensato invece del poco comprensibile SYS_LOB%

  2. Se importi con data pump e il segmento viene creato con un extent iniziale da 1 GB, vuol dire che ciò era scritto anche nella definizione dell’oggetto nel database originale.
    Data pump non ha infatti i “problemi” dei vecchi exp e imp e il loro parametro COMPRESS. O almeno così ho sempre verificato.

  3. Effettivamente non ho approfondito molto perché ieri ho scritto in fretta il post, oggi sono andato a controllare le proprietà del database di partenza ed ho notato che ha gia l'”INITIAL_EXTENT” “grande”, non ho capito come mai ma continuerò le indagini.

    • Initial extent da 1GB? Il database è un 10g, quindi molto probabilmente la tablespace è locally managed, se supponiamo che sia poi autoallocate per quanto ne so gli extents possono essere solo di 4 dimensioni: 64K, 1M, 8M e 64M. (anche LMTs con uniform size così grandi non mi sembrano verosimili).
      Boh?

      • Esatto, tablespace Locally managed e in autoallocate. Infatti quello che fa Oracle in questo caso è allora tot extent delle misure da te riportate (se fossero uniform allocherebbe trunc(1gb/)+1 extent

  4. Sì, giusto. Siccome c’era un po’ di ambiguità nel termine “initial extent”, che Rudy citando il parametro COMPRESS del vecchio export contribuiva ad aumentare, volevo solo precisare che di solito con INITIAL EXTENT si vuole intendere il primo extent.
    Il parametro INITIAL nelle DMTs si riferiva precisamente alla dimensione (in bytes) del primo extent. Nelle LMTs invece, se opzionalmente si vuole specificare, INITIAL assume il significato, come tu dici, di allocazione iniziale (in bytes) del segmento, composta di un certo numero di extents di dimensione decisa da Oracle se AUTOALLOCATE (il nostro caso)

    • Cristian, dopo quasi un anno mi è capitata una cosa simile alla tua: ho fatto un export Data Pump di uno schema SENZA DATI (content=metadata_only) e in fase di import mi sono ritrovato, con mia sorpresa, la tablespace di destinazione (auto-estensibile fino ad un massimo di 5GB) piena e l’errore relativo nel log dell’import.
      Mi sono ricordato che ero a suo tempo intervenuto nel tuo blog e allora ho pensato di aggiungere qualcosa di interessante (per chi non la sa già) sull’argomento.
      Riprendendo, ho subito pensato ai parametri di storage dei segmenti nel database d’origine (initial_extent, min_extents, …) e ho verificato che gli initial_extents erano effettivamente molto grandi (la tablespace era comunque una LMT con ASSM): probabilmente derivavano da imports eseguiti con il vecchio parametro compress che ha il default Y.

      Per risolvere il problema ho dato un’occhiata alla documentazione e ho trovato che esiste il parametro “transform” che serve per ovviare a questi inconvenienti.
      Infatti aggiungendo nel comando di import l’opzione transform=storage:n Oracle in fase di import ignorerà le clausole di storage dei segmenti.


Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

Crea un sito o un blog gratuitamente presso WordPress.com.
Entries e commenti feeds.

%d blogger cliccano Mi Piace per questo: