Jede Lösung für Oracle TNS Ineffizienzen (viele Roundtrips, Latenz) von einer Java-Anwendung?
-
28-09-2019 - |
Frage
Ich war in einer sehr langsamen SQL-Abfrage suchen (aus einer Java-Anwendung Hibernate zum Einsatz in JBoss 5.1). Diese besondere Abfrage über 10K Datensätze zurückgegeben, aber immer noch 40er Jahre nahm oder mehr.
ich am Ende den Verkehr mit der Datenbank Schnüffeln (wireshark eine Dissektor für TNS hat) und fand etwas unerwartet. Wenn Daten aus dem Server kommen, war jede Ergebniszeile in einem eigenen Paket TNS. Weiterhin wurde jedes TNS-Paket durch den Client (das heißt, die Applikationsserver), bevor die nächsten quittiert wurde aus der Datenbank gesendet. Für 10K Aufzeichnungen gibt es 10K Roundtrips, ein Paket zu erhalten und es zu bestätigen. Die Auswirkungen auf die Leistung ist sehr groß.
Das ist schrecklich ineffizient. TCP ermöglicht größere Pakete und hat eine Reihe von Mechanismen (Schiebefenster, verzögert ACKs) zu reduzieren Latenz und erhöhen den Durchsatz. Doch in diesem Fall ist es das TNS-Protokoll auf, das seine eigene Verhandlung hinzufügt.
Wenn ich die gleiche Abfrage von der Oracle SQL Developer ausführen, sehe ich nicht dieses Muster. Die Abfrage abgeschlossen in etwa 1/10 der Zeit, ohne Tausende von Rundreisen.
Kurzversion : Oracle Wire Protocol (TNS) scheint Daten zu übergeben in einer TNS-Paket pro Abfrage Ergebniszeile und erfordert jedes Paket vom Client quittiert werden, bevor der Server der nächsten sendet <. / p>
Ich habe einige Informationen zu dieser gefunden [hier] [1] (nach unten scrollen, bis dem Abschnitt ‚Die SDU und TDU Parameter in der Datei tnsnames.ora‘).
Und damit meine Frage: ist es möglich, das Verhalten der Oracle-Treiber zu steuern (I 10.2.0.4.0 bin mit), so dass das TNS-Protokoll ist effizienter? Auch dies ist eine ziemlich Standard J2EE-Anwendung in JBoss bereitgestellt.
Vielen Dank!
Lösung
Stellen Sie den SDU und TDU Parameter in tnsnames.ora und listener.ora
gesetzt, um die Stapelgröße auf 100 für den aktuellen statment.
((OracleStatement)stmt).setRowPrefetch (100);
Hinweis:
können die PREFETCHSIZE Einstellung beeinflussen die Leistung einer Anwendung. Eine Erhöhung der PREFETCHSIZE Willen reduziert die Anzahl der Umläufe erforderlich, um alle Daten zu erhalten, wird aber erhöht die Speichernutzung. Dieser Wille abhängig von der Anzahl und Größe der Spalten in der Abfrage und die Anzahl der Zeilen erwartet zurückgegeben werden. Es wird auch sind abhängig von der Speicher- und CPU Laden der JDBC-Client-Maschine. Das Optimum für einen Standalone-Client Anwendung wird anders sein, von einem stark Anwendungsserver geladen. Das Geschwindigkeit und die Latenz des Netzes Verbindung sollte auch berücksichtigt werden sein consideredconnection sollte
(von Oracle Database JDBC-Entwicklerhandbuch und Referenz )
Verfügbare Verbindungseigenschaften hier .
Haben Sie auch einen Blick auf Oracle UCP zu .
Andere Tipps
Versuchen Sie, die Fetch-Größe für Ihr satement Objekt zu erhöhen.
ich denke, die Standard-10 ist, so dass Sie mit 100 beginnen könnten versuchen.
Statement stmt = connection.createStatement(); stmt.setFetchSize(100); ResultSet rs = stmt.executeQuery("SELECT ...");