web-dev-qa-db-ja.com

行フェッチのOracleサイズを高く設定すると、アプリが遅くなりますか?

詳細 here および確認済み here として、JDBCを介してデータを照会したときにOracleが返すデフォルトの行数は10です。データベースの大量のデータを比較します。 defaultRowPrefetchを1000程度に増やすだけで、確実にアプリのパフォーマンスが向上すると思いました。結局のところ、それはパフォーマンスが遅く、約20%向上しました。

次に、数を10からゆっくり増やして、パフォーマンスを確認することにしました。 100〜200の間に設定すると、約10%の増加が見られます。ただし、これを高く設定すると、アプリのパフォーマンスが遅くなるとは思いもしませんでした。なぜこれが起こり得るのか?

ありがとう!

編集:

明確にするために、Oracle 11g R2とJava 6.を使用しています。

編集2:

さて、私は質問を明確にするために言い直したいのです。なぜなら、以下の答えから判断すると、私は自分自身を適切に表現していないからです。

フェッチサイズを高く設定すると、アプリのパフォーマンスが低下する可能性はありますか?私には、「より高速なインターネット接続、つまり太いパイプが提供されますが、ウェブの閲覧が遅くなります。

他のすべての条件は同じです。テストで確認したとおり、この1つの変更だけでアプリのパフォーマンスがどのように低下​​するかについて、私たちは非常に興味があります。

28
daveslab

考えられる説明:

  1. Oracleが最初の10ではなく最初の1000行を計算している間、Javaは何もしていません。

  2. Javaが最後の10ではなく最後の1000行を計算している間、Oracleは何もしていません。

  3. 通信プロトコル(TCP/IPなど)は長時間待機し、一度により多くのデータを処理する必要がありますが、ピークデータ転送はハードウェアの制限によって抑制されます。これはプロトコルのオーバーヘッドによって打ち消されるので、最適なフェッチサイズが必要であり、それより少なくても多くても遅くなります;))

  4. フェッチのプロセスが他のJavaコードと同期しているため、Javaが前のデータを処理した後にのみ、さらに行を要求するであり、Oracleが何も実行しない場合、さらに悪化します。平均時間。

    3人いるとします。

    • 最初のものはA4用紙を半分に折ります
    • 2つ目は、1つの部屋から別の部屋に折り畳まれた紙の山をもたらす
    • 3枚目は折り畳まれた紙からある形を切り取ります。

    1番目のスタックが2番目のスタックが戻るまで待機し、2番目のスタックが3番目のスタックがジョブを完了するまで待機する必要がある場合、スタックの大きさはどれくらいですか?

    1000のスタックは10のスタックよりも優れているとは思いません;))

23
Aprillion

すべての場合と同様に、_FAST=TRUE_設定はありません。 JDBCのデフォルトのフェッチサイズ10は状況に理想的ではありませんが、「標準的な」OLTP=アプリケーションでは問題ありませんが、実際にはthatどうやら大きなフェッチサイズはあなたの状況にも理想的ではないようですが、繰り返しますが、一度に1000を実行するのはthat悪いことではありません。

あなたが言及していない他の要因は、どのように[〜#〜] wide [〜#〜]プルされている行であるかです。データベースサーバーからネットワークを介してアプリサーバーにプルするデータのチャンクはsum(WIDTH*ROWS)であると考えてください。行の幅が5000バイトで、一度に1000をプルしている場合、フェッチごとに5 MBのデータが取り込まれます。別のケースでは、行がたった100バイトで「細い」かもしれません。その後、それらの1000をフェッチしても、10万個のピース​​が移動するだけです。

あなただけがデータがどのように戻ってくるかを知ることができるため、「一般」の場合はシステム全体でフェッチサイズを設定し、必要に応じてオッドボールクエリを個別に調整することをお勧めします。

一般に、私も100が大規模なデータ処理に適した設定であることがわかりました。これは推奨ではなく、観察を中継するものです。

12
Adam Hawkes

ところで、少なくともOracleでは、Oracleドライバーが各行で取得される(== --- ==)最大可能サイズの配列を確保するためではなく、フェッチサイズに注意する必要があります。実際のデータサイズ。したがって、ファットテーブルがある場合、メモリフットプリントが低下する可能性があります。

ここを見てください- http://www.Oracle.com/technetwork/database/enterprise-edition/memory.pdf

Oracleでは、user_tab_columnsメタデータテーブル(data_length)の列が占める最大可能スペースを見つけることができます。フェッチサイズを決定するために使用できます。

大まかなテストでは、4 * 1024 * 1024/sum(テーブルのすべての列のdata_length)が適切なフェッチサイズであることがわかりました。

6
Sumedh

正しい方法 は、setFetchSizeを使用することです。

デフォルトでは、Oracle JDBCがクエリを実行すると、データベースカーソルから一度に10行の結果セットが取得されます。これは、デフォルトのOracle行フェッチサイズ値です。行フェッチサイズの値を変更することで、データベースカーソルへの各トリップで取得される行数を変更できます。

標準JDBCでは、クエリの各データベースラウンドトリップでフェッチされる行数を指定することもできます。この数はフェッチサイズと呼ばれます。 Oracle JDBCでは、行プリフェッチ値は、ステートメントオブジェクトのデフォルトのフェッチサイズとして使用されます。フェッチサイズを設定すると、行プリフェッチ設定が上書きされ、そのステートメントオブジェクトを通じて実行される後続のクエリに影響します。

フェッチサイズは結果セットでも使用されます。ステートメントオブジェクトがクエリを実行すると、ステートメントオブジェクトのフェッチサイズが、クエリによって生成された結果セットオブジェクトに渡されます。ただし、結果セットオブジェクトでフェッチサイズを設定して、それに渡されたステートメントフェッチサイズをオーバーライドすることもできます。

6
Adam Musch

daveslab、いくつかの詳細...

アプリケーションでデータセットの処理を開始するために結果セット全体が必要な場合は、フェッチサイズを大きくすると改善される場合があります。ただし、マジックナンバーはありません。最も有益な値をテストするために必要です。

プリフェッチサイズを設定すると、アプリケーションのパフォーマンスに影響を与える可能性があります。プリフェッチサイズを大きくすると、すべてのデータを取得するために必要な往復回数が減りますが、メモリ使用量は増えます。これは、クエリの列の数とサイズ、および返されると予想される行数によって異なります。また、JDBCクライアントマシンのメモリとCPUの負荷にも依存します。最適なのは、スタンドアロンのクライアントアプリケーションが、負荷の高いアプリケーションサーバーとは異なることです。ネットワーク接続の速度と遅延も考慮する必要があります。

Oracle JDBCクライアントは、完全なプリフェッチサイズを保持するために、一部のメモリ構造を事前に初期化しているようです。したがって、プリフェッチサイズを500に設定すると、プリフェッチサイズ= 10の場合よりも50倍多くのメモリが割り当てられます。これは、特に実際にそれらの行を読み取っていない場合、GCに非常に大きな要求となります。考えてみると、通常は数行しかフェッチしない場合、GCを50倍以上実行している可能性があります。これは、アプリケーションの応答性に大きな影響を与えます。

可能であれば、クエリごとにsetFetchSizeを使用することをお勧めします。たとえば、特定のクエリが数行しか返さないことがわかっている場合は、フェッチサイズを5に設定します。クエリが1000行を返すことがわかっている場合は、100のフェッチサイズを使用します。

ヒューリスティックとして、50-100を超えることによる利点は限られています。

ご理解いただければ幸いです。Googleトランスレータを使用しています。

1
tcorteletti

Adam H.が言ったことのほとんど-すべてのタイプのシナリオに共通の設定はありません。 Oracleが行をフェッチするのに時間がかかるため、クライアントに送信する前にサーバー側で行を待機するのに費やした時間がアプリで費やされた可能性があり、プリフェッチしきい値を低く設定すると、パフォーマンスが低下します。

私が覚えていることから、Oracleもクライアント側のキャッシュを使用してスクロール可能なカーソルを提供しています。少なくともメモリの観点から、カーソルを前方のみに設定すると役立つ場合があります。少なくとも以前のバージョンのJDBCドライバーでは役立ちましたが、おそらく動作が変更されました。

Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY);
1
maximdim