La prima parte dell'articolo parla di V$SQL ed è molto interessante. Qui mi occupo della seconda parte, ovvero della cardinalità nel piano di esecuzione a seconda che venga usato il CBO o il sampling dinamico.
Nell'articolo si fa l'esempio di una tabella in cui due colonne (X e Y) hanno 12 valori distinti distribuiti uniformemente tra le righe, per cui una query del tipo
SELECT * FROM T WHERE X=5;
restituisce 1/12 delle righe, mentre
SELECT * FROM T WHERE X=5 AND Y=6;
restituisce 1/144 delle righe (1/12 * 1/12).
O almeno, questa è la selettività che si ottiene dalle statistiche sulla tabella.
Ma che cosa accade se X=Y per ogni riga? Una query come
SELECT * FROM T WHERE X=5 AND Y=6;
ritornerebbe 0 righe, quindi la stima del CBO sarebbe errata (introducendo eventuali piani di esecuzione sballati).
Utilizzando il sampling dinamico:
select /*+ dynamic_sampling(t 3) */ * from t
si ottiene invece il costo corretto, molto più basso, e quindi anche il piano corretto.
Il sampling dinamico è regolabile a vari livelli, espressi dal numero che segue il nome della tabella nell'hint all'optimizer. Il valore minimo del sampling è 32 blocchi con n=1; per i livelli da 1 a 9 vale la formula 32*2^(l-1) blocchi dove l è il livello di sampling. Nel nostro caso di n=3 si ha un sampling di 4*32=128 blocchi, per cui quasi certamente l'optimizer ha letto l'intera tabella. Per questo motivo il costo finale è molto preciso. Se il livello è 0 non si ha sampling, se è 10 il sampling viene fatto su tutti i blocchi della tabella (quindi può risultare mooolto lento).
Il dynamic sampling è quindi una possibilità in più utilizzabile nei casi in cui il CBO ci fornisce piani di esecuzione subottimali.
1 commento:
Ciao Rudy
> per i livelli da 1 a 9 vale la
> formula 32*2^(l-1) blocchi dove
> l è il livello di sampling.
Attenzione, questo è solo vero se si usa l'hint specificando la tabella (o l'alias). Quando si usa il parametro init.ora o l'hint senza specificare la tabella, il numero di blocchi è diverso. Secondo i miei test per i livelli da 1 a 9 i seguenti valori sono usati: 32, 64, 32, 32, 64, 128, 256, 1024, 4096.
Chris
Posta un commento