2011-11-29 11 views
7

Stiamo riscontrando un problema serio con una query che non fornisce spiegazioni. In SQL-plus o TOAD viene eseguito in 1/2 sec, ma quando viene eseguito da un programma C++ tramite una transazione distribuita impiegano 41 minuti. Fino a questa settimana questo ha eseguito 10.000 volte dal codice C++ in meno di un secondo.La query impiega più tempo 4800 x quando viene eseguita dal programma C++ che da SQL Plus

Nulla è cambiato nel DB o nel codice o nei server W2k che eseguono il codice.

durante l'esecuzione dal codice è molto alto db file sequenziale leggere oltre 1.000.000

quando esattamente la stessa affermazione viene eseguito da SQL più il file di db di lettura sequenziale è 8

Così stessa istruzione sta facendo 100,000x più lavoro quando si esegue tramite codice e DT che da sqlplus.

abbiamo fatto la seguente query per trovare ciò che i blocchi vengono letti SELEZIONA p1 "File #", p2 "blocco #", p3 "class #" da v $ session_wait DOVE evento = 'sequenziale db file leggere'

e sono le tabelle utilizzate nella query. Si sta leggendo le tabelle più e più ancora il spiegare piano indica solo 8 blocchi devono essere lette

entrambe le tabelle sono ~ 10 concerto di dimensioni

qui è la statment e il piano di spiegare

SELECT COUNT (*) 
    FROM student st, testinstance ti 
WHERE st.dataset_id = :b2 
    AND st.student_id = ti.student_id 
    AND ti.testinstance_id > :b1 
    AND NOT EXISTS (
      SELECT 1 
      FROM programscoringexclusion ex 
      WHERE ex.program_id = wfgeneral.getprogramid (:b3) 
      AND ex.testfamily_id = ti.testfamily_id 
      AND NVL (ex.test_level, NVL (ti.test_level, '*')) = 
                 NVL (ti.test_level, '*') 
      AND NVL (ex.battery, NVL (ti.battery, '*')) = 
                 NVL (ti.battery, '*') 
      AND NVL (ex.form, NVL (ti.form, '*')) = NVL (ti.form, '*')) 

      Plan 
SELECT STATEMENT CHOOSECost: 2      
    9 SORT AGGREGATE Bytes: 43 Cardinality: 1     
     8 FILTER    
      5 NESTED LOOPS Cost: 2 Bytes: 43 Cardinality: 1   
       2 TABLE ACCESS BY INDEX ROWID TABLE BBOX.TESTINSTANCE Cost: 1 Bytes: 32 Cardinality: 1  
        1 INDEX RANGE SCAN INDEX (UNIQUE) BBOX.XXPK0TESTINSTANCE Cost: 1 Cardinality: 1 
       4 TABLE ACCESS BY INDEX ROWID TABLE BBOX.STUDENT Cost: 1 Bytes: 11 Cardinality: 1  
        3 INDEX UNIQUE SCAN INDEX (UNIQUE) BBOX.XXPK0STUDENT Cost: 1 Cardinality: 1 
      7 TABLE ACCESS BY INDEX ROWID TABLE BBOX.PROGRAMSCORINGEXCLUSION Cost: 1 Bytes: 37 Cardinality: 1   
       6 INDEX RANGE SCAN INDEX BBOX.XXIE1PROGRAMSCORINGEXCLUSION Cost: 1 Cardinality: 1 

come possiamo vedere qual è il piano reale per una dichiarazione quando è effettivamente in esecuzione? Possiamo dire che sta leggendo i tavoli al di sopra. È possibile che il piano attuale sia diverso da quello che stiamo vedendo e in effetti sta facendo una specie di unione cartesiana o qualcosa di strano che richiede 40 minuti per risolverlo? c'è un modo per determinarlo?

risposta

5

Per trovare il piano effettivo utilizzato, è possibile eseguire query su $ sql_plan con sql_id. La cosa più facile da fare, è quello di mettere un commento nella query per renderlo unico, ad esempio

select /* FROM C++ */ .... 

e

select /* FROM SQLPLUS */ .... 

quindi eseguire la query. Interrogando da v $ sql potete trovare lo SQL_ID della query, ad esempio:

select sql_id, sql_fulltext 
from v$sql 
where upper(sql_fulltext) like '%FROM C++%'; 

Quindi, utilizzando che SQL_ID, è possibile interrogare v $ sql_plan per ottenere il piano, o meglio, utilizzare la seguente query:

select * from table(dbms_xplan.diplay_cursor('SQL ID OBTAINED ABOVE')); 
Problemi correlati