Kosmous beyond the clouds: Sviluppo, Formazione e Consulenza Informatica

Oracle DBA 9i - Cap. 8

Analizziamo le strutture fisiche all'interno delle quali sono memorizzati i dati, partendo dalla struttura più piccola, il blocco.

8.1 Il blocco

Al momento della creazione di un database, viene valorizzato il parametro DB_BLOCK_SIZE
che indica la dimensione dell'unità di misura di tutte le operazioni fisiche del database.
Ogni qualvolta che il database legge o scrive dal disco, la quantità di dati coinvolta nell'operazione di I/O è un multiplo della dimensione del blocco Oracle.
Il blocco (da adesso in poi chiamato per comodità B_O) è anch'esso una struttura logica, formata fisicamente da uno o più blocchi del Sistema Operativo (B_SO). Il valore che posso assegnare a tale parametro deve appunto essere un multiplo della dimensione del B_SO.

All'interno di B_O posso individuare le seguenti sezioni:


HEADER
Contiene informazioni sulla tipologia del blocco (ad esempio Index, Data, Undo) e sugli indirizzi del blocco stesso. Al suo interno possiamo distinguere una parte fissa (che occupa 24 Bytes) ed una parte variabile, la cui dimensione dipende strettamente dal valore del parametro INITRANS (vedi più avanti).

TABLE DIRECTORY
Contiene informazioni sulle tabelle che hanno dei record memorizzati nel blocco, ed occupa 4 bytes. Generalmente un blocco contiene records di una sola tabella, ma esistono eccezioni come le tabelle in cluster.

ROW DIRECTORY
Contiene informazioni sui records memorizzati nel blocco, come l'indirizzo di ogni singolo record, ed occupa 4 bytes per ogni record presente.

ROW DATA
Questa è la parte più consistente del blocco, in quanto è l'area che fisicamente contiene i dati degli oggetti, cioè i records.

FREE SPACE
Si tratta di una spazio libero riservato per l'inserimento dei nuovi records o per l'update degli esistenti. A volte Oracle esegue delle operazioni di coalesce per ridurre la frammentazione all'interno dei singoli blocchi causata dalle operazioni di cancellazione od update.

L'insieme dell' HEADER del TABLE DIRECTORY e del ROW DIRECTORY viene comunemente chiamato BLOCK OVERHEAD, ed ha una dimensione complessiva di circa 100 bytes, trascurabile rispetto alla dimensione complessiva del blocco.


8.1.1 Parametri

La gestione dello spazio all'interno del blocco può essere controllata mediante alcuni parametri. Diamo una spiegazione dettagliata dei più importanti:


PCTUSED
Indica la percentuale di spazio occupato nel blocco (dati + overhead), sotto il quale devo scendere per riportare come "libero" un blocco che prima era "pieno", e per default vale 40(%).
Vediamo di capire meglio come funziona. Quando viene creata una tabella, ad essa vengono associati una serie di blocchi (argomento trattato più avanti), e viene creata una lista (chiamata FREELIST) che contiene l'elenco dei blocchi liberi associati ad una tabella.
Man mano che vengono inseriti dei record nella tabella, Oracle inserisce fisicamente i records in uno dei blocchi liberi. Quando il blocco viene riempito dai record, il suo stato diventa pieno, ed il blocco viene escluso dalla FREELIST associata, per cui non verrà più preso in considerazione per ulteriori INSERT. Se adesso cancello dei record dalla tabella, essi vengono fisicamente rimossi dal blocco, ma lo stato del blocco, anche se potenzialmente potrebbe contenere dei nuovi record, non viene modificato in libero, almeno fin quando non sono stati cancellati tanti record dal blocco che la percentuale di spazio usato è scesa fino alla soglia indicata dal parametro PCTUSED.
La motivazione tecnica di questa scelta è legata al miglioramento delle performance, in quanto viene così diminuito l'Overhead dovuto al dover togliere ed inserire un blocco dalla freelist a seguito di ogni singola operazione di DELETE od INSERT. Il rovescio della medaglia è uno spreco di spazio su disco, in quanto pur potendo fisicamente accogliere nuovi records, il blocco rimane marchiato come pieno.
Tale parametro non può essere specificato per gli Indici e le Tabelle in Cluster.


PCTFREE
Indica la percentuale di spazio da riservare in ogni blocco per futuri Update, e vale per default 10. Ciò significa che in ogni blocco viene riservato il 10% di spazio, e che tale spazio viene utilizzato esclusivamente per gli eventuali update dei records memorizzati nel blocco.
Può essere specificato per tabelle, indici e cluster.

La somma dei due parametri, PCTFREE e PCTUSED, deve essere < 100.

Generalmente si consiglia di mantenere i valori di default, a meno di condizioni particolari. Ad esempio se la dimensione del blocco è notevole, i record inseriti hanno una dimensione abbastanza ridotta, e vengono effettuate numerose operazioni di DELETE, può essere il caso di aumentare il valore di PCTUSED per evitare eccessivi sprechi di spazio.
Inoltre, se la tabella non ha campi varchar, per cui lo spazio occupato è indipendente dal valore del campo, può essere il caso di diminuire il valore di PCTFREE per evitare eccessivi spreco di spazio, ma conviene sempre non esagerare, anche perché se vengono inseriti dei valori NULL (che non occupano spazio) ed essi vengono poi modificati (update), è necessario dello spazio nel blocco.

Quando viene memorizzato un record che ha una dimensione più grande della dimensione del singolo blocco, o se la tabella ha una campo di tipo LONG o LOB, Oracle utilizza due o più blocchi. Questo evento viene chiamato ROW CHAINING, e non posso evitarlo. Tuttavia non è un evento gravissimo in termini di performance, e può essere evitato solo attivando al gestione multiblocco di Oracle, e creando delle apposite strutture (sia tablespace che spazio in SGA) per trattare questi tipi di dati.

Invece un evento più grave è la ROW MIGRATION, che si verifica quando una riga, memorizzata in un blocco insieme con altri records, subisce un Update tale che la nuova dimensione del record diventa tale da non poter essere più memorizzata nel blocco, in quanto non c'è più abbastanza spazio. In questo caso Oracle sposta l'intero record in un altro blocco, viene lasciato un puntatore al nuovo record nel blocco originale, e NON vengono modificati tutti gli altri puntatori (ad esempio degli indici) al record.
Pertanto, se ad esempio viene fatto un accesso al record tramite un 'indice', Oracle è costretto a leggere prima il blocco originale, e poi da esso ricavare l'indirizzo del nuovo blocco contenente il record cercato. Questa operazione produce una grossa diminuzione delle performance, per cui è preferibile evitarla in partenza, anche se poi è possibile adottare delle contromosse di riparazione. Per questo suggerisco vivamente di non ridurre il valore del parametro PCTFREE.



INITRANS e MAXTRANS
INITRANS riserva dello spazio nell'header del blocco per le transazioni DML, e vale per default 1 per le tabelle e 2 per indici e cluster. Ogni transazione che accede al blocco, alloca certe informazioni nell'header del blocco, e se più transazioni devono utilizzare lo stesso blocco viene richiesto un ulteriore spazio, aumentando quindi la dimensione dell'header stesso.
Tuttavia, quando le transazioni terminano, questo spazio non viene più rilasciato, ed è questo il motivo per cui si imposta generalmente un limite mediante MAXTRANS, che fissa il numero massimo di transazioni che possono utilizzare il blocco in contemporanea, limitando, in pratica, la dimensione max che può raggiungere l'header. Per default MAXTRANS varia da 0 a 255 in funzione del sistema operativo usato.

Generalmente sono sufficienti i valori di default, ma in certi casi può essere utile aumentare il valore di INITRANS. Ad esempio, se la dimensione del singolo record è elevata, o se il numero di utenti che accedono alla tabella (quello che conta sono i vari INSERT DELETE o UPDATE) è basso, posso mettere un valore basso per INITRANS.
Se tabella è molto usata (tabella di controllo di un applicativo) conviene usare un valore più alto per INITRANS, perché l'operazione di aumentare la dimensione dell'header è abbastanza onerosa.




8.1.2 La gestione automatica

L'introduzione dei tablespaces Locally-managed ha permesso l'introduzione di un nuovo sistema di gestione automatica dello spazio a livello dei blocchi, attivabile al momento della creazione di un tablespace mediante l'uso della clausola "SEGMENT SPACE MANAGEMENT AUTO".
La gestione automatica prevede infatti l'utilizzo di una struttura di bitmaps al posto delle Freelist, con il conseguente desupporto ai parametri PCTUSED e FREELIST.
I vantaggi di questa soluzione sono notevoli, in quanto non occorre più cercare il valore ottimale di PCTUSED e FREELISTS, gli INSERT contemporanei sullo stesso oggetto sono più veloci, e lo spazio fisico è gestito complessivamente in maniera più efficiente.

Tuttavia non posso effettuare questa scelta se il tablespace non è locally-managed, e se vi devo memorizzare oggetti che contengono dei LOB.
Inoltre questa modalità riguarda l'intero tablespace, e non posso differenziarne singoli oggetti.


Esempio di creazione di un tablespace avente la gestione automatica dello spazio:
SQL> CREATE TABLESPACE DATI_AUTO
            DATAFILE 'C:ORACLEORADATAORCLDATI_AUTO01.dbf'
            SIZE 200M
            EXTENT MANAGEMENT LOCAL UNIFORM SIZE 512K
            SEGMENT SPACE MANAGEMENT AUTO;
8.2 Gli Extents

L'Extent è un'altra struttura logica di memorizzazione costituita da un insieme di blocchi contigui.
Anche gli Extent possono essere gestiti nel DD (se il tablespace che li contiene è Dictionary managed) o localmente tramite bitmaps (nel caso di tablespace locally-managed).

Prima di entrare nello specifico, al fine di rendere più chiaro il tutto, anticipo che un'insieme di EXTENTS formano il SEGMENT, il quale non è altro che un oggetto, come ad esempio una tabella.
Al momento della creazione della tabella, Oracle prealloca su disco lo spazio necessario per contenerne i dati, e ciò viene fatto tramite gli extents.

Riprendiamo brevemente le clausole, che sono state già trattate nel capitolo relativo ai tablespace (7.1), distinguendo in funzione della tipologia del tablespace.

Tablespace Dictionary Managed

    Nel caso in cui il tablespace sia Dictionary Managed, al momento della creazione di un oggetto posso specificare i seguenti parametri:

    INITIAL
    Indica la dimensione del primo extent allocato, generalmente espresso in Kb. Se indico ad esempio 512k, il primo extent sarà costituito da una serie di blocchi contigui. La dimensione effettiva dell'extent viene comunque arrotondata per eccesso in funzione della dimensione del blocco Oracle.

    NEXT
    Indica la dimensione del secondo extent allocato, generalmente espresso in Kb.

    PCTINCREASE
    Indica la percentuale di incremento per gli extent successi. Se ad esempio INITIAL vale 500K, NEXT vale 200K e PCTINCREASE vale 50, significa che il terzo extent allocato avrà la dimensione di 300k (200 + 200 x 50%), ed il quarto avrà la dimensione di 450K (ultimo allocato è 300 + 150), il quinto sarà di 675K (450 + 225) e così via.

    MINEXTENTS
    Indica il numero di extents da allocare su file al momento della creazione dell'oggetto. Gli altri extents verranno allocati quando verranno inseriti dati nell'oggetto, e tutti i blocchi degli extents già allocati risultano pieni.

    MAXEXTENTS
    Indica il numero massimo di extents che potranno essere allocati per quell'oggetto.


Tablespace Locally - managed

    Se il tablespace è locally-managed, non posso più utilizzare le clausole precedenti, in quanto posso avere due sole alternative:

    AUTOALLOCATE
    E' il default per la gestione degli extent, che vengono gestiti automaticamente da Oracle sia in numero che in dimensione.

    UNIFORM
    Con questa clausola indico che gli extents avranno tutti la stessa dimensione.


8.2.1 Gestione degli Extent

Il primo blocco di ogni oggetto (segment) viene utilizzato per memorizzarvi una struttura che tiene traccia di tutti gli extents appartenenti a quell'oggetto.
Quando si inserisce un nuovo record in un oggetto, e tutti gli extent allocati per quell'oggetto sono pieni, automaticamente viene ricercato, all'interno dei DF appartenenti al tablespace contenente l'oggetto, lo spazio contiguo necessario ad allocare un nuovo extent. Tale ricerca si differenzia in base alla tipologia del tablespace.

Se il tablespace è locally-managed, il nuovo extent viene allocato dopo la consultazione del bitmap di gestione di ogni singolo DF.
Se nessun DF ha lo spazio necessario, Oracle provvede ad aumentare la dimensione dei DF, sempre che essi abbiano attiva l'opzione AUTOEXTEND ON, altrimenti viene restituito errore.

Se tablespace è dictionary-managed, l'allocazione di ulteriori extents segue una serie di passaggi:

    1) Se l'extent richiesto ha dimensione > 5 blocchi, ne viene aggiunto uno in più per ridurre la possibile frammentazione; quindi viene effettuata una ricerca nei DF per individuare lo spazio esatto necessario all'allocazione dell'extent.
    (es: se ho una richiesta di 24 blocchi, Oracle cerca nel tablespace spazio libero corrispondente a 25 blocchi).

    2) Se non riesce la corrispondenza esatta viene eseguita una nuova ricerca, questa volta di un extent libero avente dimensione maggiore di quello richiesto (es: cerca spazio libero avente dimensione di 26 o più blocchi). Quando viene trovato, il procedimento di allocazione distingue i due casi:

      A) Se l'extent trovato è più grande al massimo di 5 blocchi, viene allocato per intero.
      (es se trova extent libero da 30 blocchi, lo assegna per intero).

      B) Se l'extent trovato è più grande di 5 blocchi (da 6 in poi): viene spezzato in due parti di cui la prima viene utilizzata per allocare l'extent, mentre la seconda viene aggiunta alla lista degli extents liberi.
      (es: la ricerca ha individuato un extent di 31 blocchi: i primi 25 vengono usati per allocare l'extent, mentre i 6 successivi vengono marcati come liberi).

    3) Se la fase 2 fallisce, viene eseguito Coalesce dello spazio libero nel tablespace (cioè due o più extents contigui vengono uniti in unico extent) e viene ripetuta la ricerca del punto 2.

    4) Se la fase 3 fallisce, viene controllato se i DF hanno Autoextend attivo. Nel qual caso viene aumentata dimensione del DF e la ricerca riprende dalla fase 2, altrimenti viene restituito un errore.


Gli extents vengono deallocati solo quando oggetto viene cancellato (Drop).
Se volessi liberare gli extent di una tabella o cluster potrei usare:
SQL> TRUNCATE nome_tabella DROP STORAGE;
dove:
TRUNCATE rimuove tutte le righe (ma non posso fare Rollback)
DROP STORAGE, che è il default, rimuove tutti extents oltre il MINEXTENTS.
REUSE STORAGE non rilascia gli extent.

Se invece del TRUNCATE uso il comando DELETE, i records vengono cancellati, ma gli extents non vengono rilasciati.

Se volessi invece rilasciare gli extents allocati ma non usati, posso utilizzare il comando:
SQL> ALTER [ TABLE | INDEX | CLUSTER ] nome  DEALLOCATE UNUSED;

8.2.2 Ricavare informazioni sugli extents.

Tra le viste che posso interrogare per avere informazioni sugli extents, abbiamo:

DBA_EXTENTS
Mi mostra la lista di tutti gli extents allocati per tutti gli oggetti. Da essa posso ricavare la dimensione, il nome dell'oggetto, la tipologia, il nome del tablespace e l'Id del DF che contiene l'extent.


DBA_FREE_SPACE
Mostra informazioni sugli ext liberi.



8.3 Segments

Ogni oggetto fisicamente coincide con un segment, il quale a sua volta è costituito da una serie di extents, ognuno dei quali è costituito da un'insieme di blocchi contigui.
La dimensione di oggetto è pertanto data dalla somma delle dimensioni di tutti gli extents che lo costituiscono.

Una precisazione importante: un segment può appartenere ad un solo tablespace, ed i suoi extents possono essere fisicamente memorizzati in uno qualunque dei DF del tablespace.

La modalità con la quale vengono registrate le informazioni all'interno dei blocchi e degli extents, è strettamente legata alla tipologia degli oggetti, cioè dei segments. Le tipologie possibili sono:


TABLE
Sono le classiche tabelle del database. Tuttavia se le tabelle hanno colonne di tipo LOB o VARRAY, queste colone non vengono memorizzate nello stesso segment, ma ne viene usato un altro diverso.

TABLE PARTITION
Quando si sfrutta la caratteristica di Oracle di partizionare le tabelle, ogni singola partizione viene considerata come un segment. Pertanto è possibile memorizzare con questa tecnica una tabella in più tablespace.


CLUSTER
E' un singolo segment composto da due o più tabelle, generalmente in Join tra di loro.
I dati sono memorizzati ordinati in funzione della chiave, e tutte tabelle del cluster hanno le stesse caratteristiche di storage.

NESTED TABLE
Sono tabelle in cui le colonne sono costituite da tabelle stesse (nested tables), ogni colonna viene memorizzata come segment, ognuno dei quali ha suoi parametri di memorizzazione.

INDEX
Sono gli indici creati sulle tabelle.

IOT (Index Organized Tables)
Si tratta in pratica di una tabella e di un indice combinati insieme: mentre solitamente i record di una tabella vengono inseriti casualmente nei vari blocchi, con gli IOT si definisce un indice che obbliga il Db a memorizzare i records in maniera ordinata, in funzione dell'indice definito.

INDEX PARTITION
Anche gli indici possono essere partizionati, come le tabelle

TEMPORARY
Sono quegli oggetti temporanei creati per sopperire alla insufficienza della Ram. I comandi che necessitano di molta memoria e che pertanto sono papabili di creare oggetti temporanei, sono tutti quelli che creano degli ordinamenti (sort) come:
CREATE INDEX, SELECT ... GROUP BY , SELECT DISTINCT
Generalmente vengono creati in automatico da Oracle in un Tablespace apposito (temporary tablespace) per ridurre la frammentazione.


LOB
Si tratta di un tipo di dati che può raggiungere dimensioni ragguardevoli, anche di svariati GB, e pertanto viene memorizzato in un segment apposito, lasciando nella tabella originale un semplice puntatore al dato.

UNDO
Sono i Segment che contengono i dati necessari per effettuare le operazioni di Rollback.

BOOTSTRAP
E' uno speciale segmento di SYSTEM usato per inizializzare il DD (Data Dictionary) allo startup.
Non posso fare query su di esso, ed è come se non esistesse sia per utenti che per DBA.


8.3.1 Ricavare informazioni sui segments

Tra le viste che posso interrogare per avere informazioni sui segments abbiamo:


DBA_SEGMENTS
Mostra informazioni su tutti i segments, tra cui la dimensione, il tablespace, il tipo, i parametri di storage etc.
NB: i segmenti LOB sono elencati come LOBINDEX (per gli indici) e LOBSEGMENT (i dati).


V$SORT_SEGMENT
Mostra informazioni sui segments di una data instanza usati per effettuare operazioni di sort, tra cui il numero di utenti attivi, la dimensione dei segments, gli extents usati e non usati, etc.





Vi invitiamo ad inviarci commenti, eventuali segnalazioni di errore e quant'altro
Questo documento non è un documento ufficiale della Oracle Corporation. Oracle detiene tutti i diritti sulla propria documentazione. Alcuni termini usati sono trademarks registrati. In caso di dubbi o incertezze consultate la documentazione ufficiale di Oracle o contattate il Customer Support di Oracle.
<< Capitolo 7 Capitolo 9 >>
Commenti (4)2005-10-03

03/11/2017 - viagra_cheap scrive:
Hello! cialis online , cheap cialis , viagra cheap , cheap viagra , cialis price ,
20/10/2017 - for scrive:
Hello! cialis for sale , buy cheap viagra , generic viagra , payday loans online , order cialis online ,
19/10/2017 - en scrive:
These medications for patients who lose their late cialis en verkauf Cialis teens and workup be elucidated.
14/10/2017 - cialis_generic scrive:
Hello! viagra online , cialis coupon , cialis generic , cialis online , viagra online ,