Domanda

Di colpo (ma purtroppo non so quando "improvvisamente" era, so che ha funzionato benissimo ad un certo punto in passato) una delle mie domande iniziato a prendere più di 7 secondi invece di millisecondi da eseguire. Ho 1 tabella locale e 3 tavoli si accede tramite un collegamento DB. Le 3 tabelle remote sono uniti tra loro, e uno di loro si unisce con la mia tavola locale.

clausola in cui del tabella locale richiede solo pochi Millis ad eseguire in proprio, e restituisce solo pochi (10 o 100 di al massimo) record. Le 3 tabelle remote hanno molte centinaia di migliaia, forse milioni, di record tra di loro, e se mi unisco a loro in modo appropriato ricevo decine o centinaia di migliaia di record.

io sono solo unendosi alle tabelle remote in modo che posso tirare fuori un paio di pezzi di dati relativi a ogni record nel mio tavolo locale.

Quello che sembra accadere, tuttavia, è che Oracle unisce le tabelle remote insieme e poi il mio tavolo locale per quel pasticcio alla fine. Questo sta andando sempre essere una cattiva idea, soprattutto in considerazione del set di dati che esiste in questo momento, così ho aggiunto un suggerimento /*+ LEADING(local_tab remote_tab_1) */ alla mia domanda ed ora ritorna in millisecondi.

Ho confrontato il Spiegare i piani e sono quasi identiche, tranne che per un singolo BUFFER SORT su una delle tabelle remote.

Mi chiedo cosa potrebbe causare Oracle per avvicinarsi nel modo sbagliato? È un problema di indice? Che cosa dovrei cercare?

È stato utile?

Soluzione

Quando si sceglie un piano di esecuzione, Oracle stima i costi per i diversi piani. Un'informazioni cruciali per la stima che è la quantità di righe sarà ottenere tornato da un passo del piano di esecuzione. Oracle cerca di stimare coloro che utilizzano le statistiche '', vale a dire informazioni su quante righe una tabella contiene, quanti differenti valori di una colonna contiene; Come uniformemente sono distribuiti questi valori.

Queste statistiche sono solo che le statistiche, e potrebbero essere sbagliato, che è uno dei motivi più importanti per valutazioni errate del ottimizzatore di Oracle.

Quindi, la raccolta di nuove statistiche, come descritto in un commento potrebbe aiutare. Dai un'occhiata alla documentazione sul pacchetto che DBMS_STATS. Ci sono molti modi diversi di chiamare quel pacchetto.

Altri suggerimenti

Un problema comune che ho incontrato è una query che unisce molti tavoli, dove i join formare una catena da un capo all'altro, per esempio:.

SELECT *
FROM   tableA, tableB, tableC, tableD, tableE
WHERE  tableA.ID0 = :bind1
AND    tableA.ID1 = tableB.ID1
AND    tableB.ID2 = tableC.ID2
AND    tableC.ID3 = tableD.ID3
AND    tableD.ID4 = tableE.ID4
AND    tableE.ID5 = :bind2;

Si noti come l'ottimizzatore potrebbe scegliere di guidare la query da tableA (ad esempio, se l'indice su ID0 è ben selettivo) o da Tablee (se l'indice sulla tableE.ID5 è più selettiva).

Le statistiche sui tavoli potrebbero causare la scelta tra queste due piani di equilibrio su un filo del rasoio; un giorno bene (guida da tableA), il giorno dopo le nuove statistiche di lavoro sono raccolti e tutto ad un tratto il piano alternativo di guida da Tablee ha un costo inferiore e viene scelto.

In questa circostanza, l'aggiunta di un pizzico di punta è un modo per spingere di nuovo al piano originale (cioè guidare dal tableA) senza dettare troppo al ottimizzatore (cioè non forzare la ottimizzatore di scegliere una particolare modalità di riunione).

Si sta facendo ottimizzazione delle query distribuita, e questo è una bestia difficile. Potrebbe essere che le statistiche del vostro tavolo sono in corso, ma ora i tavoli al sistema remoto sono out-of-Whack o sono cambiate. O il sistema remoto aggiunto / rimosso gli indici / modificati, e che ha rotto il tuo piano. (Questo è un ottimo motivo di prendere in considerazione la replica -. Modo da poter controllare gli indici e statistiche contro di essa)

Detto, Valutazione Oracle di cardinalità è un fattore primario nel piano di esecuzione. Un'analisi 10053 trace (Jonathan Lewis' basato sui costi di Oracle Fondamenti libro ha splendidi esempi da 8i a 10,1) può aiutare a far luce sul motivo per cui la sua dichiarazione è ora rotto e come il suggerimento LEADING lo ripara.

Il suggerimento DRIVING_SITE potrebbe essere una scelta migliore se si sa che si desidera sempre le tabelle locali da unire prima di andare dopo che il sito remoto; chiarisce la vostra intenzione senza guidare il piano il modo in cui un suggerimento LEADING avrebbe fatto.

Potrebbe non essere rilevante, ma ho avuto una situazione simile volta in cui la tabella remota era stato sostituito da una vista a tavolo singolo. Quando era un tavolo la query optimizer distribuita 'visto' che aveva un indice. Quando divenne una vista che non poteva vedere l'indice più e non potrebbe costare un piano che utilizza un indice sull'oggetto remoto.

E 'stato alcuni anni fa. Ho documentato la mia analisi al momento qui .

RI,

E 'difficile essere sicuri circa la causa dei problemi di prestazioni senza vedere il codice SQL.

Quando una query di Oracle si esibiva ben prima, e improvvisamente inizia l'esecuzione di male, di solito è collegato a uno dei due problemi:

  

A) Le statistiche non sono aggiornati. Questa è la cosa più semplice e veloce per controllare, anche se si dispone di un processo batch di pulizia che dovrebbe prendersi cura di esso ... sempre doppio controllo.

     

B) Volume di dati / cambio modello di dati.

Nel tuo caso, l'esecuzione di una query distribuita su più database rende 10 volte più difficile per Oracle per gestire le prestazioni tra di loro. E 'possibile mettere queste tabelle in un unico database, i proprietari dello schema forse separati in un unico database?

I suggerimenti sono notoriamente fragili, come Oracle è sotto alcun obbligo di seguire il suggerimento. Quando il volume di dati o modello cambia un po 'di più, Oracle può semplicemente ignorare il suggerimento e fare quello che pensa sia meglio (cioè peggiore; -.).

Se non si può mettere queste tabelle tutto in un unico database, allora vi consiglio di guardare a rompere la query in due affermazioni:

  1. Inserisci il sub-SELECT per copiare i dati esterni in una tabella temporanea globale nel database corrente.
  2. Seleziona dalla tabella temporanea globale di unirsi con l'altra tabella.

Si avrà il controllo completo sulla performance del punto 1 di cui sopra senza ricorrere a suggerimenti. Questo approccio scale tipicamente bene, fornendo si prende il tempo di fare il tuning delle prestazioni. Ho visto questo approccio a risolvere molti problemi di prestazioni complesso.

L'overhead per Oracle per creare un nuovo tavolo, o inserire un mucchio di dischi, è molto più piccolo di quanto la maggior parte delle persone si aspettano. Definire inoltre una tabella temporanea globale riduce il carico di.

Matthew

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top