【SQL】副問合せを使うSQLをチューニングする方法


ここではORACLEデータベースのSQLで、副問合せ(サブクエリー)を大量に使ったSQLのチューニング方法を紹介します。

SQLの実行計画の見方や確認方法については↓で紹介していますので参考にしてください。
>>【ORACLE】SQLの実行計画の見方
>>【ORACLE】SQLの実行計画を取得する方法

副問合せを使うSQLをチューニングする方法

一般的に、ORACLEは1つのSQLでたくさんの副問合せがあったり、5つ以上のテーブルを参照したりすると、適切でない実行計画を作る可能性が高くなります。これまでの経験でもそうでした。ヒントが効かなくなることもありました。

しかし、現場のプログラムやSQLを見ると、たくさんの副問合せや5つ以下のケースって意外と少ないです。特に業務アプリで、日々改修が入っているようなSQLだと10とか20、最近見たものだと40くらいのテーブルを参照していました。当然、副問合せもたくさん紛れ込んでいました。

例えば、下記のSQLのように、複数の副問合せが存在してSQLが複雑になっている場合です。副問合せの中がで更に副問合せがされているケースは、実行計画がより複雑になって、遅くなっているケースがあります。

こういった場合は、副問合せを使うのを止めます。代わりにワークテーブルを作成して、SQLを分割し、実行していきましょう。

これによりSQLがシンプルに、簡潔になるため、オプティマイザが適切な実行計画を作成しやすくなり、結果的に処理時間の短縮が狙えます。バッチ処理などで、処理時間が長いSQLほど効果が出せると思います。

手間もありますし、プログラムの改修も必要かもしれませんが、処理時間の改善が急務であれば、やってみる価値はあります。

もちろん実装前にワークテーブルを作成してみて、性能が向上することを確認することをおすすめします。

◆副問合せを使って遅い場合 例

select
t1.*
from
(
SELECT a.* FROM table1 a
)t1
inner join (
SELECT a.* FROM table2 a
)t2
on ( t1.col1 = t2.col1)
inner join (
SELECT a.* FROM table3 a
) t3
on ( t1.col1 = t3.col1)
inner join (
SELECT a.* FROM table4 a
)t4
on ( t1.col1 = t4.col1)
inner join (
SELECT
a.*
FROM
table5 a
inner join (select b.* from table6 b) b
on (a.col1 = b.col1)
)t5
on ( t1.col1 = t5.col1)
;

◆置き換えの例

–ワークテーブルへのデータ登録
insert into t1 select * from table1;
insert into t2 select * from table2;
insert into t3 select * from table3;
insert into t4 select * from table4;
insert into t5 select * from (
SELECT
a.*
FROM
table5 a
inner join (select b.* from table6 b) b
on (a.col1 = b.col1)
)t5;

–対象データの抽出
select
t1.*
from
t1
inner join t2
on ( t1.col1 = t2.col1)
inner join t3
on ( t1.col1 = t3.col1)
inner join t4
on ( t1.col1 = t4.col1)
inner join t5
on ( t1.col1 = t5.col1)
;

最後に

最後までお読みいただきありがとうございます。

SQLのチューニング方法は↓で紹介していますので参考にしてください。
>>SELECT文のSQLチューニング方法まとめ