2

非常に大きなクエリがあります。かなり大きいので、ここには投稿しません (順序とグループ化を備えた 6 レベルのネストされたクエリがあります)。クエリには、 を介して渡される 2 つのパラメータがありますPreparedStatement.setString(index, value)。SQL Developerを介してクエリを実行すると(クエリパラメータを手動で実際の値に置き換える)、クエリは約10秒実行され、約15000行が返されます。しかし、PreparedStament を使用して Java プログラムで実行しようとすると、変数で失敗しORA-01652(unable to extend temp segment)ます。Java プログラムから単純なステートメントを使用しようとしましたが、問題なく動作します。また、変数なしで PreparedStatement を使用する場合 ( を使用せずsetString()、パラメータを手動で指定する場合) も正常に動作します。

したがって、問題は PreparedStatemnt パラメータにあると思われます。

そのパラメーターのメカニズムはどのように機能しますか? 単純なステートメントは正常に機能するのに、準備されたステートメントが失敗するのはなぜですか?

4

1 に答える 1

1

バインド変数のピークに関する問題が発生している可能性があります。

同じクエリでも、実際のバインド変数によって最適なプランが大きく異なる場合があります。10g では、Oracle は使用されるバインド変数の最初のセットに基づいて実行計画を作成します。11g では、さまざまなバインド変数に対して複数のプランを作成する機能である適応型カーソル共有により、この問題がほぼ修正されました。

この問題を解決するためのいくつかのアイデアを次に示します。

リテラルを使用する これは、人々が想定するほど必ずしも悪いことではありません。クエリの適切なバージョンが 10 秒で実行される場合、クエリのハード解析のオーバーヘッドは無視できます。ただし、SQL インジェクションを避けるために注意が必要な場合があります。

ハード解析を強制する Oracle にすべてのクエリ を強制的にハード解析させる方法はいくつかあります。1 つの方法は、クエリ内のテーブルの 1 つで NO_INVALIDATE=>FALSE を指定して DBMS_STATS を呼び出すことです。

バインド変数のピーク/ヒントを無効にする 関連するヒストグラムを削除するか、OldProgrammer が提供するリンクのパラメーターの 1 つを使用してこれを行うことができます。これにより計画は安定しますが、必ずしも正しい計画が選択されるとは限りません。適切なプランを選択するためにヒントを使用する必要がある場合もあります。ただし、入力のすべての組み合わせに対して適切な計画を立てられるとは限りません。

11g へのアップグレード これはオプションではないかもしれませんが、この問題はアップグレードの計画を開始するもう 1 つの良い理由です。

于 2013-07-30T18:50:10.353 に答える