■同じSQLなのに実行計画が変わる!?
先日、非常に重たいSQLのチューニングを行うべく様々なテストを行っていた中で、
少し不思議な出来事がありました。
全く同じSQLを2連続で実行すると、実行計画が変わるのです。
全く同じなのだから同じ実行計画で実行されてほしいのですが、
やはりOracleのオプティマイザはそう簡単に思ったとおりに動いてはくれません・・・
よくよく調べてみると、Oracle11gR2からの新機能「Cardinality Feedback」が関係していることがわかりました。
■Cardinality Feedback(カーディナリティ フィードバック)とは
実行計画を生成するオプティマイザのインプット情報に、実データのカーディナリティ(データの種類の多さ)情報を加えることによって、より最適な実行計画を生成する機能です。
ハードパース時、統計情報と実データのカーディナリティに乖離がある場合、
そのカーディナリティを記録し、その後に実行される全く同じSQLの実行計画は、実データを加味して最適になるように変更されます。
つまりアーキテクチャを簡単に示すと、
★1回目実行時
ハードパース
⇒ 実行計画作成
⇒ SQL実行
⇒ 統計情報と実データのカーディナリティに乖離があるか確認
A.乖離がない場合、そのまま結果出力
B.乖離がある場合、メモリ上にカーディナリティを記録した後、結果出力
★2回目実行時
ハードパース
⇒ カーディナリティ調整し、再度実行計画作成
⇒ SQL実行
と、なります。
実際にCardinality Feedbackが発生してるかどうかを確認するには、
実行計画を取得し、Notesに以下のような文言が出力されているかを確認します。
Notes
-----
- cardinality feedback used for this statment
統計情報を適切でない場合でも、データと統計情報の乖離を補正してくれるので、
非常に便利な機能だと言えます。
ただし、何点か考慮事項があります。
・統計情報を固定した場合でも、実行計画が変化する可能性がある
⇒意図的に統計情報を固定し、実行計画の変動を防ごうとしている場合でも、
変動してしまうかもしれないということです。
・カーディナリティを記録した後の実行は必ずハードパースとなる
⇒ハードパースに時間がかかるSQLの場合、考慮が必要です。
Oracleのオプティマイザは裏でいろいろなことをやっているので、
それを把握しておけば、パフォーマンスチューニングの時に役立つかもしれませんね。
0 件のコメント:
コメントを投稿