我々のデータ処理アプリケーションのパフォーマンスのベンチマークを実行しているとき、我々はFOO_TABLE空で始まり、その後、別のスレッドでは、我々は同じレコードを選択しながら、のようなクエリを使用して処理することから一つのスレッドからレコードを挿入します。一緒にOracleはクエリプランをどのくらい頻繁に変更しますか?
select * from FOO_TABLE where ID > ?
1つのチャンクで選択されたレコードの数を制限するために、Javaでの
stmt.setMaxRows(5000);
をJavaで使用します。 (IDにギャップがあるため、ここではBETWEENは使用したくありません)。テストが停止されるまで、チャンクの処理を5000回続けます。
ここでは、アプリケーションのパフォーマンスが低下し、Oracle側で何が起きているかを確認したところ、「select * from FOO_TABLE where ID>」というクエリプランに気づいたことに驚きました。 IDにPKインデックスを使用する代わりにテーブルスキャンを行います。
アプリケーションを再起動した後(ただし、表を切り捨てずに)、Oracleはreasonに戻り、PK索引を使用しました。
私の説明は、空がほぼ空だったときにテーブルをスキャンすることをお勧めしますが、このクエリプランを改訂していないと考えました。これは私の質問に私をもたらします:どのくらいの頻度でOracleがクエリプランを改訂しますか?
私はアプリケーションを再起動したのでしょうか? 1時間後にプールされた接続をリサイクルするので、私はこれについていくつか疑問を抱いています(したがって、1時間以上接続できません)。
一定の時間が経過したのでしょうか?
テーブルがほとんど空であっても、Oracleがスキャンを実行しないようにする方法はありますか?
環境情報: - を11gの神託 - JDBCクライアント(Java 6の)
UPDATE 2011年10月25日:私は、Oracle 10gで回帰テストを行なったし、問題は同じであるので、それが発生していないですどちらも動的カーソルの共有によって固定されます。 Markが最初に述べたように、構造の変更やテーブル統計の再計算といった大きなイベントがない限り、計画は改訂されません。
最終的に私はPKによるアクセスを強制するためのヒントを追加しましたが、オプティマイザがこれを理解できるはずだったと思います。検索条件に一致するPKがある場合は、小さなテーブルでもパフォーマンスの差はあまり重要ではありません。
実際11gです。だから、あなたはある時点で計画を改訂することをオラクルが期待していますか?約1日と数千万件の記録が残っていたが、計画は変わっていなかった。事実、このテーブルスキャンのために、アプリケーションのスループットはほとんど0に落ちました。あなたが言及している適応カーソル共有には特別な設定が必要ですか? –
すでに使用中のプランとは異なるプランを必要とするかもしれない別のバウンド値がない限り、プランは適応カーソル共有のもとで変更されません。多くのデータを表にロードする場合は、統計を再集計する方がよいでしょう。 –