今日はサブクエリとJOINで同じ結果が得られる場合
どっちがいいでしょう?!という話です。
まずは検証テーブルとデータを示します。
shopsテーブル |
ID |
shopname |
delflag |
1 |
A店舗 |
0 |
2 |
B店舗 |
0 |
3 |
C店舗 |
1 |
4 |
D店舗 |
0 | |
dataテーブル |
ID |
d |
val |
1 |
2006/01/01 0:00:00 |
1000 |
1 |
2006/02/01 0:00:00 |
1200 |
1 |
2006/03/01 0:00:00 |
1300 |
1 |
2006/04/01 0:00:00 |
1400 |
2 |
2006/01/01 0:00:00 |
2000 |
2 |
2006/02/01 0:00:00 |
2200 |
2 |
2006/03/01 0:00:00 |
2300 |
2 |
2006/04/01 0:00:00 |
2400 |
3 |
2006/01/01 0:00:00 |
3000 |
3 |
2006/02/01 0:00:00 |
3200 |
3 |
2006/03/01 0:00:00 |
3300 |
3 |
2006/04/01 0:00:00 |
3400 |
4 |
2006/01/01 0:00:00 |
4000 |
4 |
2006/02/01 0:00:00 |
4200 |
4 |
2006/03/01 0:00:00 |
4300 |
4 |
2006/04/01 0:00:00 |
4400 | |
で、検証に使用したSQLが以下の2つになります。
shopsテーブルでdelflagが1となっているIDを対象に
dataテーブルを取得し、valの合計値を求めるSQLになります。
SELECT
data.id,
sum(data.val)
FROM
data,
shops
WHERE
data.id = shops.id AND
shops.delflag = 1
GROUP BY
data.id;
|
SELECT
id,
sum(val)
FROM
data
WHERE
id IN
(
SELECT
id
FROM
shops
WHERE delflag = 1
)
GROUP BY id ;
|
今回はSQLServer2005での実行検証なので、画像で実行計画をみせます♪
JOINではテーブルスキャン→ソート→マージ・ジョイン(ジョイン処理です)→計算→出力 ですが、
サブクエリではテーブルスキャン→ネスティド・ループジョイン(ジョイン処理です)→ソート→計算→出力になっています。
この例ですと、サブクエリのネスティド・ループジョインの方がコストが低く出ていますね。
(マージ・ジョインは17%、ネスティド・ループ・ジョインは1%)
なので、例ですとネスティド・ループ・ジョインとなるサブクエリの方がコスト低いと考えられます。
#JOINのソートは32%×2、サブクエリのソートは63%なので大差ないかな~
ついでに、例題のSQLからdelflagの条件を抜いた実行計画をお見せします。
今度はハッシュ・ジョインとネスティド・ループ・ジョインに変わりましたね。
で、ソートのコストが32%と63%になりました。
トータルとして66%と34%なので、サブクエリの方が良いSQLといえると思います。
<まとめ>
JOINとサブクエリは共に結合という処理が動いていますが、
上記例の場合、shopsテーブルから得られるデータを必要としていないため、
サブクエリでまとめ、データを取得した方がコストが低く抑えられる。
さて、次は何にしようかな。
スキーマとセキュリティの話と、
今回出てきた、ジョインの種類を説明するのと・・・・
あとチューニングネタ思いついたら・・・かな?
#なんせ、更新とろいので何がくるやら(^^;
#リクエストは随時募集しています。書く時期は未定となりますが(ぉぃ