2009-08-27 2 views
5

Ciao ho una query a un sistema Oracle che implica una vista che unisce altre tabelle aplicando un TO_NUMBER() alla chiave primaria delle tabelle.Domanda lenta in Java da JDBC ma non in altri sistemi (TOAD)

Se eseguo la query utilizzando TOAD, la query è molto veloce (1 secondo per 800 reg). Se faccio la stessa query in un programma java da JDBC con un letterale String (non una query parametrizzata), anche il tempo è buono.

Ma se utilizzo una query parametrica da un PreparedStatement, la query impiega 1 minuto per recuperare gli stessi registri. So che utilizzando valori costanti si ottiene un piano di esecuzione distinto rispetto all'utilizzo dei parametri ... ma se rimuovo le funzioni TO_NUMBER nei join della vista, anche la query parametrica è veloce.

  • I parametri/unione TO_NUMBER() impediscono l'utilizzo dell'indice PK delle tabelle unite?
  • c'è una soluzione per risolvere questo (ho bisogno dei parametri sulla query e anche la funzione TO_NUMBER)?

P.D. sry per il mio cattivo inglese

+0

le tabelle sono partizionate? – skaffman

risposta

1

senza ulteriori informazioni, possiamo solo supporre che un indice non venga utilizzato con la funzione to_number() applicata alla colonna. Come mostrato in this SO question, una conversione di tipo può impedire all'ottimizzatore di utilizzare un indice.

In generale:

  • quando si aggiunge una funzione a una colonna (ad esempio: to_number(id)) l'ottimizzatore non sarà in grado di utilizzare gli indici regolari su quella colonna,
  • se è possibile, dovresti usare la colonna raw. Per Esempio: invece di WHERE trunc(col) = DATE '2009-08-27' si dovrebbe usare: WHERE col >= DATE '2009-08-27' AND col < DATE '2009-08-28'
  • se proprio dovete applicare una funzione a una colonna, è possibile utilizzare un function-based index
+0

so che l'aplicazione di una funzione su una colonna può impedire l'uso dell'indice della colonna, ma la cosa strana è che accade solo quando la query è parametrizzata – Telcontar

+0

@Telcontar: cosa potrebbe accadere è che il tipo di dati della costante (con Toad o con un sql costruito dinamicamente e il tipo di dati dei tuoi parametri sono diversi. Ciò potrebbe portare a una situazione in cui il piano per una query parametrizzata è subottimale a causa della conversione implicita. Puoi darci un semplice esempio di una query in cui si riscontra questo problema? –

+0

La query è SELECT * FROM V_DAT_AJPR_CON_DESCRIP_C WHERE ENTIDAD = 7777 E TO_NUMBER (CFPERIOD) = TO_NUMBER (251) E CFSUBGRP = 'S0000' E ID_VERSION = 6 dove i quattro valori sono dinamico vista uso multiplo si unisce altre tabelle di forma CFPERIOD, ID, Campo_1 ... FIELD_N e il PK è (CFPERIOD, ID) e unirsi con la vista è TO_NUMBER (V.CFPERIOD) = TO_NUMBER (T.CFPERIOD) e V .ID = T.ID – Telcontar

1

Controllare che il tipo di dati della variabile Java passato nel parametro è compatibile con il tipo di dati Oracle. Ho visto sintomi simili ai tuoi quando si passava Java TIMESTAMP attraverso una variabile di bind confrontata con le colonne Oracle DATE - query stringa letterale OK, test case in PL/SQL con (data) bind OK, codice Java w/mismatch non OK.

[Modifica] Penso che tu abbia fornito alcune informazioni aggiuntive dal post originale. Il modo migliore per capire cosa sta accadendo con le forme leggermente diverse (binds letterali) della query da ambienti diversi (Java vs Toad) è abilitare la traccia durante l'esecuzione e confrontare i percorsi di esecuzione dai file di traccia risultanti. Ciò richiederà che tu abbia accesso all'host del database per recuperare i file.

  • In Toad, aprire una finestra interattiva SQL (io non uso rospo ma sono sicuro capirete cosa intendo) e eseguire il comando SQL "alter sessione set sql_trace = true "
  • eseguire la query - che sarebbe stata una buona idea di aggiungere un commento alla query come ad esempio '/ * Toad con letterali * /'
  • per il test Java, costruire un banco di prova che emette il "alter sessione ..." dichiarazione e quindi esegue la query Anche in questo caso, aggiungere un commento alla query per identificarlo come proveniente dal test Java
  • Non preoccuparti per girare il tracciamento off -.. Questo accadrà quando la sessioni sono scollegati e in alcuni casi è preferito il metodo disconnessione fermare la traccia.
  • capire dove il file di traccia sul l'host del database sono da "selezionare valore del parametro v $ dove nome come 'user_dump_dest' "
  • Trovare i file .TRC ricercando la query stringhe di commento
  • utilizzare l'utilità TKPROF dalla riga di comando OS per elaborare il file di traccia - "TKPROF filename.trc TKPROF filename.out"
  • esaminare/pubblicare i percorsi di esecuzione e volte che vedete.
+0

il confronto dei dati è tra numeri e stringhe, alcune stringhe iniziano con 0 che non riesco a rimuovere dalle tabelle della vista (non riesco a scriverle) – Telcontar

+1

Ho aggiunto alcune informazioni nel mio risposta originale sul tracciamento dell'esecuzione che dovrebbe aiutarci/noi ad analizzare cosa sta realmente accadendo. – dpbradley

+0

Sry ho dimenticato questa domanda (che è già senza risposta), ma non posso fare il test che suggerisci, io non sono il dba e posso solo creare tabelle/viste, procedure, pacchetti ... ma non tracciare le query . Lo passo al DBA ma non penso che faccia nulla – Telcontar

0

Controllare che qualcuno non ha impostato la proprietà oracle.jdbc.defaultNChar = true

Questo a volte è fatto per risolvere i problemi unicode ma significa tutte le colonne vengono trattati come nvarchars. Se si dispone di un indice su una colonna varchar, non verrà utilizzato perché oracle deve utilizzare una funzione per convertire la codifica dei caratteri.