9

CLOB(平均20k文字)を取得するために、JDBCを使用してOracle 10gに対してクエリを実行しています(最新のドライバーとUCPをデータソースとして使用)。ただし、パフォーマンスはかなり悪いようです。100個のLOBのバッチ取得には、平均で4秒かかります。私の観察から判断すると、操作もI/OでもCPUでもネットワークバウンドでもありません。

私のテスト設定は次のようになります。

PoolDataSource dataSource = PoolDataSourceFactory.getPoolDataSource();
dataSource.setConnectionFactoryClassName("...");
dataSource.setConnectionPoolName("...");
dataSource.setURL("...");
dataSource.setUser("...");
dataSource.setPassword("...");

dataSource.setConnectionProperty("defaultRowPrefetch", "1000");
dataSource.setConnectionProperty("defaultLobPrefetchSize", "500000");

final LobHandler handler = new OracleLobHandler();
JdbcTemplate j = new JdbcTemplate(dataSource);

j.query("SELECT bigClob FROM ...",

        new RowCallbackHandler() {

            public void processRow(final ResultSet rs) throws SQLException {

                String result = handler.getClobAsString(rs, "bigClob");

            }

        });

}

フェッチサイズを試しましたが、役に立ちませんでした。私は何か間違ったことをしていますか?JDBCを使用するときにCLOBの取得を高速化する方法はありますか?

4

4 に答える 4

7

結果セットの合計サイズは 10,000 です - 初期コストを取得する全体にわたって測定されます

クエリに Order By はありますか? ソートする必要がある場合、10K 行はかなりの量です。

また、PK の取得は、CLOB 全体の取得と比べて公平なテストではありません。Oracle は、おそらく多数のテーブル行を 1 つのブロックに格納しますが、各 CLOB (4K を超える場合) は、それぞれ一連のブロック内に行外に格納されます。したがって、PK のリストのスキャンは高速になります。また、おそらく PK にインデックスがあるため、Oracle はインデックス ブロックをすばやくスキャンでき、テーブルにアクセスすることさえできません。

4 秒は少し長いように見えますが、ディスクから読み取ってネットワーク経由で Java プログラムに転送できる必要があるのは 2MB です。ネットワークが問題になる可能性があります。セッションの SQL トレースを実行すると、時間が費やされている場所 (ディスク読み取りまたはネットワーク) が正確に示されます。

于 2009-10-07T13:32:20.700 に答える
6

大きなデータを格納するためにOracleLOBタイプのデータを使用した私の過去の経験は良くありませんでした。varchar2のようにローカルに保存されるため、4k未満の場合は問題ありません。4kを超えると、パフォーマンスが低下し始めます。おそらく、数年前に最後に試したときから状況が改善された可能性がありますが、参考までに過去に見つけたものは次のとおりです。

クライアントはOracleサーバーを介してLOBを取得する必要があるため、次の興味深い状況を考慮することができます。

  • オラクルがそれをキャッシュすることを決定した場合、LOBデータは制限されたSGAキャッシュを他のデータ型と競合します。clobデータは一般的に大きいため、他のデータをプッシュする可能性があります
  • オラクルがデータをキャッシュしないことを決定した場合、LOBデータのディスク読み取りが不十分になり、データをクライアントにストリーミングします。
  • 断片化はおそらくまだ遭遇していないものです。アプリケーションがLOBを削除し、OracleがLOBを再利用しようとするかどうかを確認します。オラクルがLOB用にディスクをオンラインで最適化することをサポートしているかどうかはわかりません(インデックス用にありますが、以前に試したときは時間がかかります)。

平均20kの100lobに対して4sについて言及したので、lobあたり40msです。各ロブは個別のロブロケーターを介して取得する必要があることに注意してください(デフォルトでは結果セットに含まれていません)。これは、各lobの追加の往復であると思います(少し前のことなので、これについては100%確信が持てません)。その場合、連続した順序で、往復ごとに少なくとも5ミリ秒の延長時間がかかると思います。 、 右?その場合、パフォーマンスは最初に順次lobフェッチによって制限されます。これは、SQLの実行とLOBコンテンツのフェッチに費やされた時間を追跡することで確認できるはずです。または、投稿の前の回答で提案されているようにlob列を除外することでこれを確認できます。これにより、lobに関連しているかどうかがわかります。

幸運を

于 2009-10-07T17:52:10.177 に答える
6

私は同様の問題を抱えていて、JDBC LOB が LOB にアクセスするときにネットワーク呼び出しを行っていることを発見しました。

Oracle 11.2g JDBC Driver では、プリフェッチを使用できます。これにより、アクセスが10倍高速化されました...

statement1.setFetchSize(1000);
if (statement1 instanceof OracleStatement) {
    ((OracleStatement) statement1).setLobPrefetchSize(250000);
}
于 2014-04-17T15:52:05.573 に答える
2

すべての役立つ提案をありがとう。問題への回答としてフラグが立てられていますが、私の答えは、良い解決策がないように見えるということです。並列ステートメント、さまざまなストレージ特性、事前に並べ替えられた一時を使用してみました。テーブルなど。操作は、トレースまたはプランの説明を通じて見える特性に拘束されていないようです。CLOB が関係している場合、クエリの並列処理でさえ大雑把に見えます。

間違いなく、11g 環境ではなく atm. 10gで困っています。

ここで、CLOB を前処理してサイズが最適化されたバイナリ RAW にする、データベースへの追加のラウンドトリップを選択しました。以前の展開では、これは常に非常に高速なオプションであり、オフラインで計算されたキャッシュを維持する手間をかける価値があるでしょう。誰かがより良いアイデアを思いつくまで、キャッシュは無効になり、永続的なプロセスと AQ を使用して更新されます。

于 2009-10-12T19:58:45.363 に答える