2011-11-29 34 views
7

Estamos teniendo un problema grave con una consulta que desafía la explicación. En SQL-plus o TOAD se ejecuta en 1/2 segundo, pero cuando se ejecuta desde un programa C++ a través de una transacción distribuida, demora 41 minutos. Hasta esta semana, esto se ha ejecutado 10.000 veces desde el código C++, todo en menos de un segundo.La consulta tarda 4800x más cuando se ejecuta desde el programa C++ que desde SQL Plus

No ha cambiado nada en la base de datos o el código o los servidores W2k que ejecutan el código.

cuando se ejecuta desde el código que ha muy alto db archivo secuencial leer más de 1.000.000

cuando exacta misma instrucción se ejecuta desde SQL más la lectura secuencial de archivos DB es 8

Así mismo enunciado está haciendo 100.000X más trabajo cuando se ejecuta a través de código y DT que desde sqlplus.

hicimos la siguiente consulta para encontrar lo que los bloques se leen p1 SELECT "archivo #", p2 "bloque #", p3 "clase #" de v $ session_wait DONDE evento = 'archivo db secuencial leer'

y son las tablas utilizadas en la consulta. Está leyendo las tablas una y otra vez sin embargo, el explicar el plan indica sólo 8 bloques deben ser leídos

ambas tablas son ~ 10 concierto en tamaño

aquí es la DECLARACIÓN y el plan explicar

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 

¿Cómo podemos ver cuál es el plan real para una declaración cuando se está ejecutando realmente? Podemos decir que está leyendo las tablas de arriba. ¿Es posible que el plan real sea diferente al que vemos y de hecho está haciendo algún tipo de unión cartesiana o algo extraño que demora 40 minutos en resolverse? hay alguna manera de determinar eso?

Respuesta

5

Para encontrar el plan real utilizado, puede consultar v $ sql_plan con sql_id. La cosa más fácil de hacer, es poner un comentario en la consulta para que sea único, por ejemplo

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

y

select /* FROM SQLPLUS */ .... 

A continuación, ejecute la consulta. Mediante la consulta de v $ sql se encuentra la SQL_ID de la consulta, por ejemplo:

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

Luego, utilizando esa SQL_ID, puede consultar V $ SQL_PLAN para obtener el plan, o mejor, utilizar la siguiente consulta:

select * from table(dbms_xplan.diplay_cursor('SQL ID OBTAINED ABOVE')); 
Cuestiones relacionadas