Oracle
 sql >> Database >  >> RDS >> Oracle

Quali sono le implicazioni sulle prestazioni della clausola Oracle IN senza join?

Se le statistiche sulla tua tabella sono accurate, dovrebbe essere molto improbabile che l'ottimizzatore scelga di eseguire una scansione della tabella piuttosto che utilizzare l'indice della chiave primaria quando hai solo 1000 elementi hardcoded in WHERE clausola. L'approccio migliore sarebbe quello di raccogliere (o impostare) statistiche accurate sui tuoi oggetti poiché ciò dovrebbe far accadere automaticamente cose buone piuttosto che provare a fare molta ginnastica per aggirare le statistiche errate.

Se assumiamo che le statistiche siano imprecise al punto da indurre l'ottimizzatore a ritenere che una scansione della tabella sarebbe più efficiente rispetto all'utilizzo dell'indice della chiave primaria, potresti potenzialmente aggiungere un DYNAMIC_SAMPLING suggerimento che costringerebbe l'ottimizzatore a raccogliere statistiche più accurate prima di ottimizzare l'affermazione o una CARDINALITY suggerimento per sovrascrivere la stima della cardinalità predefinita dell'ottimizzatore. Nessuno di questi richiederebbe la conoscenza degli indici disponibili, richiederebbe semplicemente di conoscere l'alias della tabella (o il nome se non esiste un alias). DYNAMIC_SAMPLING sarebbe l'approccio più sicuro e robusto, ma aggiungerebbe tempo alla fase di analisi.

Se stai creando un'istruzione SQL con un numero variabile di parametri codificati in un IN clausola, probabilmente creerai problemi di prestazioni per te stesso inondando il tuo pool condiviso con SQL non condivisibile e costringendo il database a dedicare molto tempo all'analisi di ciascuna variante separatamente. Sarebbe molto più efficiente se si creasse una singola istruzione SQL condivisibile che potrebbe essere analizzata una volta. A seconda di dove il tuo IN da cui provengono i valori delle clausole, potrebbe assomigliare a

SELECT *
  FROM table_name
 WHERE primary_key IN (SELECT primary_key
                         FROM global_temporary_table);

o

SELECT *
  FROM table_name
 WHERE primary_key IN (SELECT primary_key
                         FROM TABLE( nested_table ));

o

SELECT *
  FROM table_name
 WHERE primary_key IN (SELECT primary_key
                         FROM some_other_source);

Se ti sei ridotto a una singola istruzione SQL condivisibile, oltre a evitare il costo di rianalizzare costantemente l'istruzione, avresti una serie di opzioni per forzare un piano particolare che non comporta la modifica dell'istruzione SQL. Diverse versioni di Oracle hanno diverse opzioni per la stabilità del piano:ci sono schemi memorizzati , Gestione del piano SQL e profili SQL tra le altre tecnologie a seconda della versione. Puoi usarli per forzare piani particolari per particolari istruzioni SQL. Tuttavia, se continui a generare nuove istruzioni SQL che devono essere analizzate di nuovo, diventa molto difficile utilizzare queste tecnologie.