JavaアプリからのOracle TNSの非効率性(多くの往復、レイテンシ)のソリューションはありますか?
-
28-09-2019 - |
質問
私は非常に遅いSQLクエリを見ていました(JBOSS 5.1に展開されたHibernateを使用したJavaアプリから発信されます)。この特定のクエリは約10kの記録を返しましたが、それでも40秒以上かかりました。
私は最終的にデータベースでトラフィックを嗅ぎ取ることになりました(WiresharkにはTNSの分離器があります)、予期しない何かを見つけました。サーバーからデータが来るとき、各結果行は独自のTNSパケットにありました。さらに、次のTNSパケットがデータベースから送信される前に、各TNSパケットはクライアント(つまり、アプリサーバー)によって認められました。 10kのレコードには、パケットを取得して確認するための10kの往復があります。パフォーマンスへの影響は膨大です。
これはひどく非効率的です。 TCPは、より大きなパケットを許可し、多くのメカニズム(スライド式ウィンドウ、遅延アック)があり、遅延を減らしてスループットを増加させます。ただし、この場合、独自の交渉を追加するのはTNSプロトコルです。
OracleのSQL開発者から同じクエリを実行した場合、このパターンは表示されません。クエリは、数千回の往復なしで、約1/10で完了します。
短縮版: :Oracle's Wire Protocol(TNS)は、クエリの結果行ごとに1つのTNSパケットにデータを渡すようで、サーバーが次のパケットを送信する前に、各パケットをクライアントによって確認する必要があります。
これについての情報を見つけました[こちら] [1](「TNSNAMES.oraファイルのSDUおよびTDUパラメーター」のセクションまでスクロールダウンします)。
したがって、私の質問:Oracleドライバーの動作を制御することは可能ですか(10.2.0.4.0を使用しています)。繰り返しますが、これはJBossに展開されているかなり標準のJ2EEアプリです。
どうもありがとう!
解決
調整します sdu と TDU tnsnames.oraおよびlistener.oraのパラメーター
現在の統計でバッチサイズを100に設定します。
((OracleStatement)stmt).setRowPrefetch (100);
ノート:
プリフェッチサイズを設定すると、アプリケーションのパフォーマンスに影響を与える可能性があります。プリフェッチサイズを増やすと、すべてのデータを取得するために必要なラウンドトリップの数が減りますが、メモリの使用量が増加します。これは、クエリ内の列の数とサイズ、および返される予定の行数によって異なります。また、JDBCクライアントマシンのメモリとCPU負荷にも依存します。スタンドアロンのクライアントアプリケーションの最適は、重度のロードされたアプリケーションサーバーとは異なります。ネットワーク接続の速度と遅延も考慮する必要があります。
(から OracleデータベースJDBC開発者ガイドとリファレンス )
使用可能な接続プロパティ ここ.
また、見てください Oracle UCP それも。
他のヒント
サットメントオブジェクトのフェッチサイズを増やしてみてください。
デフォルトは10だと思うので、100から始めようとするかもしれません。
Statement stmt = connection.createStatement(); stmt.setFetchSize(100); ResultSet rs = stmt.executeQuery("SELECT ...");