
Oracle SQLチューニング(第27回)「NULL処理構文の理解と効率的なSQLの作成」(3/7回)
「NULL処理構文の理解と効率的なSQLの作成」の三回目である今回は、「グループ関数(COUNT,SUM,MAX,MIN)とNVL処理」と題して、お送りします。では、早速始めましょう。
7.3 グループ関数(COUNT,SUM,MAX,MIN)とNVL処理
グループ関数に対して誤ったNULL処理が原因で誤ったデータを抽出する問題は、たびたび発生します。 NULL演算が間違って発生する可能性のある深刻な問題は、抽出しようとするデータの結果が異なり、データの整合性を損なう可能性があることと、同時にこの点をユーザが誤った結果であると認識することが難しいということです。 今回のケースでは、誤った NULL 処理で結果の値がなぜ変わるのか、そしてなぜ発見するのが難しいのかを調べ、この 2 つの場合の解決策を調べてみましょう。
[改善前SQL]
テーブルNULL_T2統計情報およびINDEX情報
テーブルNULL_T3統計情報およびINDEX情報
[改善後SQL]
[改善前SQL]のようにスカラーサブクエリを毎度実行して値を抽出した部分を結合(Hash Join)に変更して性能が改善しました。 改善前/後のデータを比較してみればデータもまた完ぺきに一致して性能が改善されたと判断されます。 しかし、悲しいことに改善前/後SQLで抽出されたデータは作成者が意図したのと違ったデータでした。 しかしSQLのどの部分が誤ったデータを抽出するかは発見するのが容易ではありません。
それでは、なぜ間違ったデータが抽出されたのでしょうか? その理由に対して調べてみることにしましょう。
[改善後SQL]は以下のような意図を持って作成しましたが、SQLに正しく反映されず、間違ったデータが抽出されました。
- インライン ビューT1ではNULLデータが抽出されない。
- T2.C3,T3.C3はNullableカラムで、NULLが抽出された場合にはT1.C3_SUM値をそのまま抽出しなければならない。
作成意図は上記と同じなのですが改善前/後SQLの場合、T2.C3、T3.C3の値のうちNULLが存在すルトSUM(C3)はNULLを抽出することになります。 これは、SUM関数の処理中にNULLデータに対して処理が行われていないためです。 明らかにSQLの作成意図は、T2.C3、T3.C3の値がNULLであればT1.C3_SUM値のままを抽出することを望みましたが、NULL+T1.SUM(C3)演算によって誤ったTotal Sum値が抽出されてしまいます。 SUM 関数を使用する際、演算対象となるデータの中にNULL 値が含まれる可能性がある場合には、以下のように必ずNVL 関数を利用した処理が追加で必要となります。
[最終改善後SQL]
引き続き他のグループ関数であるCOUNT,SUM,MAX,MINのNULL処理がどのように実行されるのか下の例題SQLを通じて調べてみることにしましょう。
テスト結果を見れば、COUNTを除いたSUM,MAX,MINはNULLデータをNULLでリターンするということが分かります。 したがって抽出されたデータを利用してまた他の修飾(数式)演算が別に進行されなければならない場合にはNVL処理を必ず実行し、誤った結果値が抽出されることを防ぐことができます。
今回は、ここまでとなります。いかがでしたか?次回は、「NULLABLEカラム使用による非効率COUNT関数処理」です。それでは、次回まで see you ^^