Qualche soluzione per le inefficienze di Oracle TNS (molti viaggi di andata e ritorno, latenza) da un'app Java?

StackOverflow https://stackoverflow.com/questions/3893943

  •  28-09-2019
  •  | 
  •  

Domanda

Stavo osservando una query SQL molto lenta (originariamente da un'app Java che utilizza Hibernate distribuito in JBoss 5.1).Questa particolare query ha restituito circa 10.000 record, ma ha comunque richiesto 40 o più secondi.

Alla fine ho annusato il traffico con il database (wireshark ha un dissettore per TNS) e ho trovato qualcosa di inaspettato.Quando i dati provenivano dal server, ciascuna riga di risultati era nel proprio pacchetto TNS.Inoltre, ogni pacchetto TNS è stato riconosciuto dal client (cioèil server dell'app) prima che quello successivo fosse inviato dal database.Per i record da 10.000, sono necessari 10.000 viaggi di andata e ritorno per ottenere un pacchetto e riconoscerlo.L'impatto sulle prestazioni è enorme.

Ciò è terribilmente inefficiente.TCP consente pacchetti più grandi e dispone di una serie di meccanismi (finestre scorrevoli, ACK ritardati) per ridurre la latenza e aumentare il throughput.Tuttavia, in questo caso è il protocollo TNS in alto che aggiunge la propria negoziazione.

Se eseguo la stessa query da Oracle SQL Developer, non vedo questo modello.La query viene completata in circa 1/10 del tempo, senza migliaia di viaggi di andata e ritorno.

Versione breve:Il protocollo Wire Protocol (TNS) di Oracle sembra passare i dati in un pacchetto TNS per riga di risultati della query e richiede che ciascun pacchetto venga riconosciuto dal client prima che il server invii quello successivo.

Ho trovato alcune informazioni al riguardo [qui] [1] (scorri verso il basso fino alla sezione "I parametri SDU e TDU nel file tnsnames.ora").

E quindi la mia domanda:è possibile controllare il comportamento del driver Oracle (sto usando 10.2.0.4.0) in modo che il protocollo TNS sia più efficiente?Ancora una volta, questa è un'app J2EE piuttosto standard distribuita in JBoss.

Molte grazie!

È stato utile?

Soluzione

Sintonizza il SDU E TDU parametri in tnsnames.ora e listener.ora

Per impostare la dimensione batch su 100 per l'estratto conto corrente.

  ((OracleStatement)stmt).setRowPrefetch (100);

Nota:

Impostare la dimensione del prefetch può influire l'esecuzione di una domanda.Aumentando la dimensione del prefetch ridurre il numero di viaggi di andata e ritorno richiesto per ottenere tutti i dati, ma sarà aumentare l'utilizzo della memoria.Questo sarà dipende dal numero e dalle dimensioni del colonne nella query e il numero di righe da restituire.Lo farà. dipendono anche dalla memoria e dalla CPU caricamento della macchina client JDBC.La soluzione ottimale per un client standalone applicazione sarà diverso da un server di applicazioni molto carico.Il velocità e latenza della rete anche il collegamento dovrebbe essere consideratoil collegamento dovrebbe essere considerato

(da Guida e riferimento per gli sviluppatori JDBC di Oracle Database )

Proprietà di connessione disponibili Qui.

Dai un'occhiata anche a OracleUCP pure.

Altri suggerimenti

Prova ad aumentare la dimensione di recupero per il tuo oggetto di istruzione.

Penso che il valore predefinito sia 10, quindi potresti provare a iniziare con 100.

Statement stmt = connection.createStatement();
stmt.setFetchSize(100);
ResultSet rs = stmt.executeQuery("SELECT ...");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top