質問: ### 質問内容 Oracle SQLの質問です。初心者の為、ご教示頂きたく宜しくお願い致します。 OracleのViewからTABLEへデータを投入するとき、TABLEとViewのキー項目を結合し、「DELETE/INSERT」または「MERGE」を発行し投入しています。 Functionが使われているViewをsourceにした場合の「DELETE/INSERT」と「MERGE」で処理速度が大幅に異なりました。 その後、該当SQLについて実行計画を取得した所「DELETE/INSERT」と「MERGE」でINDEX使用の挙動が異なることがわかりました。(後述参照) 結合している部分(WHERE句かONクか)が関係しているのか等々調べましたが、それらしい記述を見つけられませんでした。 SQL文の組み方の問題なのか、それともWHERE結合・ON結合の挙動の問題なのか判断が付かず、なぜDELETE文の方だけINDEXが使われていないのかという説明が出来ず困っています。 『全く同じ結合条件』を使用した2つのSQL文について、 何故INDEXの使用の挙動が異なるのかご教示頂けないでしょうか。 ### 実行計画取得時のFilterの表示 1DELETE/INSERTを行っているSQL文について実行計画を取得すると INDEXが使用されていないという結果が出ました。 (TABLE ACCESS FULL) また、実際に発行されているSQLと異なった表示になっています。 ``` FUNCTION(SOURCE.col1):=B1 AND FUNCTION(SOURCE.col2):=B2 AND FUNCTION(SOURCE.col3):=B3 ``` 2同じキーを指定したMERGE文の場合は、INDEXが使用されているという結果が出ました。 (INDEX RANGE SCAN) こちらの挙動は想定通りの挙動です。 ``` TEST_TABLE.col1:=FUNCTION(SOURCE.col1) AND TEST_TABLE.col2:=FUNCTION(SOURCE.col2) AND TEST_TABLE.col3:=FUNCTION(SOURCE.col3) ``` ### 実行計画取得時のSQL文(項目名は仮名に変更しています) ``` 【SQL1 DELETE/INSERT】 DELETE FROM TEST_TABLE t WHERE EXISTS (SELECT 1 FROM TEST_VIEW s WHERE t.col1=s.col1 AND t.col2=s.col2 AND t.col3=s.col3) ``` ``` 【SQL2 MERGE】 MERGE INTO TEST_TABLE t USING TEST_VIEW s ON (t.col1=s.col1 AND t.col2=s.col2 AND t.col3=s.col3) WHEN MATCHED THEN UPDATE SET t.col1=s.col1 AND t.col2=s.col2 AND t.col3=s.col3 t.col4=s.col4 AND t.col5=s.col5 WHEN NOT MATCHED THEN INSERT VALUES (s.col1,s.col2,s.col3,s.col4,s.col5) ``` ### 試したこと DELETE文発行時、ViewからFunctionを外すとINDEXが使用されるようになることは確認しています。
回答: 関数を使用しているビューを使用している事と、相関副問い合わせという事が相まってインデックススキャンされないのではないかと思います。 以下の様な副問合せであれば改善されないでしょうか。 ``` DELETE FROM TEST_TABLE t WHERE (col1, col2, col3) in ( SELECT col1, col2, col3 FROM TEST_VIEW ) ``` 理由という事なら、deleteでは相関副問い合わせを使用しているからでしょうね。 相関副問合せは駆動表を処理しながら問合せを行うのが基本です。 ですので、突合する先にインデックスが無いなら、駆動表についてもインデックスを使用しない方が効率的だと判断するからです。