03 luglio 2008

Vantaggi del sampling dinamico

Ho recentemente letto un curioso aricolo di Tom Kyte su Oracle Magazine sul dynamic sampling e i suoi vantaggi rispetto alle statistiche usate dal cost-based optimizer (CBO) in alcuni casi particolari.

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:

Anonimo ha detto...

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