コストベースオプティマイザを使用するにはオプティマイザ統計情報が必要です。
ゆえに、オプティマイザ統計情報の自動収集、手動収集を適宜実行し、有効なオプティマイザ統計情報を維持することが重要になります。
ただし、一時表のオプティマイザ統計情報の収集については注意が必要です。
一時表にはトランザクション固有の一時表とセッション固有の一時表の2種類の一時表が存在します。
トランザクション固有の一時表の場合、データはトランザクション内でのみ有効となります。つまり、トランザクションをコミットした時点でデータがクリアされてしまいます。
ゆえに、オプティマイザ統計情報を収集しても全く意味がありません。
むしろデータが 0 件であるというオプティマイザ統計情報が残ることにより、不適切な実行計画が選択され、パフォーマンスに重大な影響を与える可能性が懸念されます。
セッション固有の一時表の場合、データはセッション内でのみ有効となります。つまり、セッションを切断した時点でデータがクリアされてしまいます。
ただし、コミットしてもセッションを切断しなければデータは保持されますので、一時表にデータを INSERT した後、同一セッション内でオプティマイザ統計情報を収集すれば、その後、同一セッション内で実行される SQL 文の解析時に利用されます。
この方法はきわめて限定的な状況においては効果的かもしれません。
しかし、他のセッションに対して悪影響を与える可能性もありますので、このようなオプティマイザ統計情報の収集はできれば避けたほうがよいと思われます。
以上のことから、一時表については原則的にオプティマイザ統計情報を収集せず、動的サンプリングを適用するのが望ましいと考えられます。
オプティマイザ統計情報を収集しないようにするには、まずオプティマイザ統計情報を削除し、その状態のままロックします。
BEGIN DBMS_STATS.DELETE_TABLE_STATS('owner_name','table_name'); DBMS_STATS.LOCK_TABLE_STATS('owner_name','table_name'); END; /
動的サンプリングを適用させるためには、OPTIMIZER_DYNAMIC_SAMPLING 初期化パラメータを 2 以上に設定します
このようにすることによって、オプティマイザ統計情報がない状態を維持し、常に動的サンプリングを適用することができるようになります。
私が経験した事例の中には、丸1日かけても終わらなかった処理が、一時表のオプティマイザ統計情報を削除・ロックし、動的サンプリングが適用されるようにすることによって数分に改善されたという凄まじいものもありました^^;
些細なことですが、このように深刻なパフォーマンス問題を引き起こしかねないので要注意です。
【関連エントリ】
[Oracle] オプティマイザ統計情報の収集は基本的にOracle任せでOK
[Oracle] オプティマイザ統計情報を手動収集する
[Oracle] ルールベースオプティマイザの廃止と動的サンプリング
[Oracle] 揮発性の高い表のオプティマイザ統計情報の収集について