Gli Access Path sono le modalità con cui i dati sono recuperati da un database Oracle.
Volendone fare un elenco, abbiamo:
- Full Table Scans
- Rowid Scans
- Index Scans
- Assessing I/O for Blocks, not Rows
- Index Unique Scans
- Index Range Scans
- Index Range Scans Descending
- Index Skip Scans
- Full Scans
- Fast Full Index Scans
- Index Joins
- Bitmap Indexes
- Cluster Access
- Hash Access
- Sample Table Scans
Questo tipo di scansione legge tutte le righe della tabella filtrando quelle che non rispondono al criterio di selezione dello statement. Oracle legge i blocchi di dati sequenzialmente e siccome questi sono adiacenti, riesce a leggere più blocchi contigui in una singola chiamata I/O grazie al parametro di inizializzazione DB_FILE_MULTIBLOCK_READ_COUNT.
Oracle utilizza questo tipo di access path nei seguenti casi:
- Mancanza di Indici
- Grandi quantità di dati: se l’ottimizzatore rileva che saranno usati la maggioranza dei blocchi della tabella, allora userà un Full Table Scan anche in presenza di indici.
- Piccole tabelle: quando una tabella occupa meno blocchi di quelli indicati nel parametro DB_FILE_MULTIBLOCK_READ_COUNT sotto l’high water mark, allora il database può leggere i dati in una singola chiamata I/O.
- Alto grado di parallelismo
Un alto grado di parlallelismo per una tabella costringe l’ottimizzatore a un full table scan. In questo caso esaminare il campo DEGREE della ALL_TABLES per determinare tale grado.
- Si usa l’hint FULL(alias tabella)
In questo caso è possibile usare anche l’hint CACHE o NOCACHE per indicare all’ottimizzatore dove mettere i dati recuperati. L’opzione CACHE pone i blocchi nel buffer-cache alla fine dell’LRU list.
- Si esegue la query in parallelo
Rowid Scan
Il rowid è un identificativo di una riga in cui è specificato il datafile e il data-block contenente la riga. Per accedere a una tabella by rowid, oracle prima li deve ottenere dalle righe selezionate dalla clausola where dello statement attraverso un index-scan di uno o più indici della tabella. Dopodiché localizza ogni riga basandosi sul suo rowid. Quindi l’ottimizzatore utilizza un rowid generalmente dopo averlo ricavato da un indice.
Index Scan
In questo metodo, una riga è recuperata scansionando l’indice, usando i valori delle colonne specificate nello statement. Se lo statement richiede solo le colonne dell’indice, allora oracle legge i dati direttamente dall’indice senza accedere alla tabella. Un indice contiene non solo il valore della colonna indicizzata, ma anche il rowid delle righe della tabella che hanno quel valore.
Un index scan può essere dei seguenti tipi:
- Index Unique Scan
Questa scansione ritorna al massimo un singolo rowid. Viene eseguito se lo statement contiene un vincolo UNIQUE o PRIMARY KEY che garantisce l’accesso a una sola riga. Può essere utilizzato anche quando nello statement è specificato l’hint INDEX(alias index_name). In tale caso però si specifica di usare l’indice ma non la modalità di accesso (range scan o unique scan).
- Index Range Scan
E’ la classica operazione di accesso ai dati. Essa può essere limitata o non limitata. I dati sono restituiti in ordine ascendente rispetto alle colonne indicizzate. Più righe con gli stessi valori delle colonne sono ordinate in modo ascendente secondo il rowid. Se si utilizza la clausola ORDER BY l’ottimizzatore verifica se l’ordinamento corrisponde a quello di base dell’access path, se è così allora evita il sort. L’ottimizzatore usa un range scan quando trova una o più colonne principali di un indice specificate nella condizione del WHERE. La condizione colonna1 like ‘A%’ non si traduce mai in un range scan. E’ possibile utilizzare l’hint INDEX_DESC() per ottenere un range scan ordinato in senso discendente.
L’ottimizzatore è influenzato nella sua decisione della percentuale di blocchi a cui accedere, non dal numero di righe. Questa percentuale è detta index clustering factor (indice del fattore di raggruppamento). Questo index clustering factor è una proprietà dell’indice e si riferisce alla diffusione dei valori di una colonna dentro un data-block di una tabella. Un basso indice indica che singole righe sono concentrate in pochi blocchi, al contrario un alto indice indica che singole righe sono “spalmate” randomicamente su più blocchi. Quindi un elevato index clustering factor comporta un aumento del costo del range scan dello statement.
- Index Skip Scan
Spesso la scansione dei blocchi di un indice è più veloce che la scansione di blocchi di tabelle. Questo tipo di access path consente di suddividere un indice composito in sottoindici più piccoli. Nello skip scan la colonna iniziale dell’indice non viene indicata nello statement, quindi il database determina un numero di sottoindici logici per il numero di valori distinti della colonna iniziale. E’ vantaggioso quando la colonna principale dell’indice, quella che viene saltata, non contiene molti valori.
- Full Scan
Un full index scan elimina le operazioni di ordinamento. Esso legge dai singoli blocchi. Oracle può usare tale access path nelle seguenti situazioni:
- Una clausola Order By che corrisponde alle seguenti richieste è presente nella query:- Tutte le colonne in Order By sono indicizzate- L’ordine delle colonne in Order By è lo stesso delle colonne dell’indice- La clausola Order By contiene tutte le colonne dell’indice o un suo sott’insieme.
- La query richiede un sort merge join. In questo caso il database può eseguire un full index scan al posto di un full table scan, seguito da un ordinamento. Ciò può avvenire nei seguenti casi:- Tutte le colonne nella query sono anche nell’indice.- L’ordine delle colonne indicate nella query è lo stesso delle colonne principali dell’indice.- Una clausola Group By è presente nella query e le colonne indicate sono presenti nell’indice.
- Fast Full Index Scan
Rappresenta un’alternativa al full table scan quando l’indice contiene tutte le colonne che sono necessarie alla query e almeno una colonna ha un vincolo NOT NULL. Questo tipo di scansione prende i dati dall’indice stesso senza accedere alla tabella. Il database legge l’intero indice mediante letture multiblocco e diversamente dal full index scan, può essere eseguito in parallelo.
E’ possibile specificare il fast full index scan nel parametro di inizializzazione OPTIMIZER_FEATURES_ENABLE oppure con l’hint INDEX_FFS.
- Index Joins
Un index Joins rappresenta un hash-join di molti indici che insieme contengono tutte le colonne della tabella indicate nella query. Se il database usa questo access path allora l’accesso alla tabella non è necessario in quanto tutti i dati possono essere recuperati dai valori delle colonne degli indici. Non è possibile usare un index join per eliminare le operazioni di ordinamento. L’hint per abilitare tale access path è INDEX_JOIN.
- Bitmap Indexes
Un Bitmap Indexes utilizza un bitmap per i valori chiave e una funzione di mappatura che converte ogni posizione del bit in un rowid.
Cluster Access
Il cluster scan è usato per recuperare tutte le righe che hanno lo stesso cluster key value da una tabella memorizzata in un cluster indicizzato. In un cluster indicizzato, il database memorizza tutte le righe con lo stesso cluster key value in uno stesso blocco dati. Nell’eseguire un cluster scan, Oracle prima prende i rowid da uno delle righe selezionate dalla scansione sul cluster index, poi localizza le righe basandosi su questo rowid.
Hash Access
In un hash cluster tutte le righe con lo stesso hash value sono memorizzate nello stesso blocco dati. Oracle utilizza un hash scan per localizzare le righe in un hash cluster basandosi su un hash value. Oracle prima calcola l’hash value applicando la funzione di hash al cluster key value specificato nello statement, poi scansione i blocchi contenenti le righe con quell’hash value.
Sample Table Scan
Si tratta di una scansione “a campione” dei dati di una tabella oppure di un complesso statement. Questo access path viene utilizzato quando la clausola from di uno statement include la clausola SAMPLE oppure SAMPLE BLOCK. Per eseguire questa modalità il database legge una specifica percentuale di righe (o blocchi nel caso SAMPLE BLOCK) della tabella. Esempio: lo statement SELECT * FROM employees SAMPLE BLOCK (1); legge l’1% dei blocchi della tabella.
L’ottimizzatore sceglie l’access path da applicare basandosi su 2 fattori:
- Disponibilità dell’access path per quello statement
- Stima dei costi di esecuzione usando ogni access path disponibile o una combinazione di questi.
Viene scelto l’access path o combinazione di essi con costo minore.