2010-11-02 17 views
9

Actualmente estoy enfrentando un problema por el cual una consulta SQL específica tarda unos 30 segundos en emitirse desde mi aplicación Java pero < 1 segundo en un SQL-client (SQL Developer).Problemas de rendimiento con JDBC

En la pregunta,
Slow query in Java by JDBC but not in other systems (TOAD), se sugiere que el uso de un PreparedStatement con destino a las variables Java podría realizar la consulta ejecutar mucho más lento que en el SQL-cliente (SAPO en ese caso), ya que Oracle se está confundido acerca de qué índices para usar. ¿Podría ser esto un problema con un PreparedStatement sin parámetros también?

¿Cuál podría ser el problema?

La consulta se ve algo así como

select 
sum(col1), 
sum(col2), 
max(select ...) 
from view_ 
where time_id = get_time_id(to_date('2010-10-10','yyyy-mm-dd')) 

donde view_ es una vista compleja que contiene agregados de mesas y otros puntos de vista complejos. La consulta se ejecuta como un PreparedStatement pero sin ningún parámetro. No parece hacer una diferencia si usamos una declaración preparada o simplemente declaraciones simples.

Dado que el plan de ejecución es bastante grande que no se puede publicar todo si aquí, pero la diferencia relevante parece ser:

 
UNION-ALL 
TABLE ACCESS FULL GVC_WH.PLAYER_FACT_DAILY TABLE 37 6717151 596,934.317 19940 240 7621178231 19502 
 
UNION-ALL 
TABLE ACCESS BY INDEX ROWID GVC_WH.PLAYER_FACT_DAILY TABLE 38 2657 236.120 2429 30 20544658 2428 
INDEX RANGE SCAN GVC_WH.PK_AGG_PLAYER INDEX (UNIQUE) 37 2657 16 1 638743 16 

Cuando el primer fragmento es de cuando se ejecuta con el JDBC Thin Client y el segundo desde que se ejecuta dentro de SQL Developer. No está recogiendo el índice correcto cuando se ejecuta como una declaración (no importa si uso una declaración preparada o no) con el Thin Client de JDBC. La diferencia de tiempo i 30 segundos para el primero y 0.5 segundos para el segundo.

¿Podría ser que usar la función get_time_id prohíbe el uso del índice cuando se usa a través de JDBC, aunque no funcione en la columna y aunque parezca estar funcionando en SQL Developer?

+2

¿Puede obtener y publicar los planes de consulta para los dos casos?Y para mayor claridad, ¿eres coherente sobre cómo estás midiendo el rendimiento? Es algo común medir accidentalmente el momento en que SQL Developer devuelve la primera fila frente al momento en que su código Java recupera la última fila, que puede ser sustancialmente diferente. –

+2

Comenzaría mirando el plan de ejecución (mediante dbms_xplan.display cursor) generado por cada método (TOAD vs. Java). Eso debería decirle si la base de datos trata las consultas de manera diferente. Si es así, preste mucha atención a la sección de predicados, ya que es probable que le proporcione algunas pistas sobre por qué (por ejemplo, la conversión de tipo de datos implícita se produce a partir de la versión de Java y hace que Oracle no pueda usar un índice) – Craig

+0

Véase también http://stackoverflow.com/questions/3976184/oracle-query-ora-01652-unable-to-extend-temp-segment-but-only-in-some-versions – symcbean

Respuesta

1

Es muy posible que podría estar golpeando problemas con pico variable de enlace debido a los predicados que se ha pasado. Pruebe a ejecutar la consulta con las siguientes para confirmar (es decir, tiempos de ejecución consistente)

alter session set “_optim_peek_user_binds”=false; 

son los estadísticas actualizado en todos los objetos?

Como justin publicado, también, asegúrese de que también está midiendo correctamente. Sin la consulta completa, será difícil proporcionar información adicional.

+0

¿A qué variables se refiere? Como dije, la declaración preparada no tiene parámetros. Además, la diferencia de rendimiento es de órdenes de magnitud para obtener solo una fila. Las estadísticas están actualizadas. –

+0

Dependiendo del valor del parámetro CURSOR_SHARING Oracle puede obligar a vincular variables en las instrucciones. http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/initparams035.htm – Serxipc

2

Intentaré ejecutar un trace en la base de datos mientras uso la aplicación.

Luego debería poder ver la consulta que se está ejecutando y el plan de ejecución real. Esto le mostrará exactamente lo que está sucediendo, es decir, si está recogiendo los índices o no.

0

Compruebe para asegurarse de que alguien no ha determinado la propiedad oracle.jdbc.defaultNChar = true

veces esto se hace para resolver problemas Unicode pero significa que todas las columnas son tratados como nvarchars. Si tiene un índice en una columna varchar, no se usará porque Oracle tiene que usar una función para convertir la codificación de caracteres.

Cuestiones relacionadas