今回もパフォーマンス差異をちらっと。
今回は2つのテーブルを使用します。
この2つでUSER_INFOはIDとそれに紐づく名前が入っています。
DATにはIDとSUBID、それに対するVALがあります。
#(余談)
#1IDで複数のVALを持つためにSUBIDがついています。
#インデクス張っていないので、あんまり関係ないけど(w
?
この2テーブルで
ユーザ名とID毎で合算したVALの合計値を取得するSQLを2本出します。
パターン1 |
パターン2 |
SELECT
SUM(val),
(
SELECT
n
FROM
user_info
WHERE
user_info.id = dat.id
) name
FROM
dat
GROUP BY id
|
SELECT
SUM(val),
user_info.n
FROM
user_info JOIN dat ON
user_info.id = dat.id
GROUP BY user_info.n;
|
パターン1はDATからデータをID毎にグループ化し、VALの合計値を出したデータと
SELECT句でサブクエリを使って名前をつけています。
?
パターン2はDATとUSER_INFOをIDでJOIN(結合)して、名前とVALの抽出し、名前ごとにVALを合算しています。
?
まずはUSER_INFO、DAT共に1レコードが入った状態で実行した
クエリプランを見ていただきます。
#これは私の牛ノートで実際に動かした結果です。
パターン1の方がクエリコスト低く出ていますね。
?
ではデータをUSER_INFOに1000件、DATに1000*100件(ID=1000パターンかつSUBID=100パターン)のデータを入れて
同じようにクエリプランをとったものを見てもらいます。
?
今度はパターン2の方がクエリコストが低くなりましたね。
?
?
これは2つのSQLにそれぞれ特性があるからです。
パターン1はDATで取得した結果N件に対し、N回、USER_INFOを読みに行きますが、
パターン2はDATとUSER_INFOを結合した後に結果を出しているからです。
?
よって、1回目の1行しかない状態ですと、
・2テーブルの結合より、N回テーブルを読み行ったほうがコストが低く
2回目のデータが多い場合ですと
・N回テーブル読みするよりも、2テーブルを結合したほうが早い
ということがいえると思います。
?
このようにSQLでもデータによって性能の良し悪しが変わることもあるので、
SQLを考える際は、データの分布についても着目していただけたら幸いです。
?