こんにちは、さるまりんです 🐒🔧
SQLを書いていると、
- とりあえずJOINでつなぐ
- 必要なテーブルをどんどん追加する
- 気づいたらたくさんのテーブルをつないでいる
こんな状態になること、ありませんか?
そして、
「あれ?なんかこのSQL遅いな…」
と感じることもあります。
今回はそうなる前に一度立ち止まって考えたい、
JOINと設計の関係
について見ていきたいと思います。
とりあえずJOIN、になっていない?
例えばこんなSQLです。
SELECT
u.id,
u.name,
o.id AS order_id,
p.name AS product_name
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id
WHERE u.id = 1;
正しいSQLですし、動きます。
でもこれ、
本当にこの構造で取得する必要がありますか?
と一度疑問を持つことが大切だと思っています。
JOINが増えると何が起きる?
JOINが増えると、内部ではこういうことが起きています。
- テーブル同士の組み合わせを作る
- 条件に合うものを探す
- 不要な行を削る
つまり、
データ量が掛け算で増える可能性がある
ということです。
例えば、
- users:1件
- orders:100件
- order_items:1000件
みたいな構造だと、
内部的にはかなりの組み合わせを処理することになります。
これが「遅くない?」の正体です。
※実際にはDBのオプティマイザが順序を調整しますが、JOINが増えるほどコストが増える傾向があるのは変わりません。
よくあるアンチパターン
■ ① 必要以上にJOINしている
「とりあえず全部つなぐ」
これはかなり多いです。
実際には、
- 表示に必要なテーブルの必要なカラムだけ
- 今の処理で必要な範囲だけ
に絞れることが多いです。
■ ② フィルタが後ろにある
WHERE u.id = 1
これがSQLの後ろの方にあると、
絞り込み前に大量のJOINが走る可能性があります
(DBによっては最適化されますが、期待しすぎは危険です)
a.id = b.a_id と JOIN の違い
ここ、なんとなく書いてしまっていることが多いポイントです。
例えばこの2つ。
-- パターン①
SELECT *
FROM a, b
WHERE a.id = b.a_id;
-- パターン②
SELECT *
FROM a
JOIN b ON a.id = b.a_id;
これらは、
意味としてはほぼ同じ(内部的にも同様に扱われることが多い)
です。
じゃあ何が違うのか?
違いは主に3つあります。
■ ① 可読性
FROM a, b
WHERE a.id = b.a_id;
条件なのか結合なのかが分かりにくい
JOIN b ON a.id = b.a_id;
「結合条件」として明確に表現できる
■ ② 書き間違いリスク
カンマ区切りの場合、
FROM a, b, c
と書いて、
WHERE a.id = b.a_id;
だけだと…
cが全件結合(クロス結合)になる
という事故が起きます。
■ ③ OUTER JOINが書けない
LEFT JOIN
RIGHT JOIN
は、JOIN構文でしか書けません。
実務ではJOIN構文を使うのが基本です
大事なのは「SQL」ではなく「設計」
ここが今回一番伝えたいところです。
JOINが増えているとき、
SQLをいじる前に、設計を疑う
という視点が大事です。
■ このテーブル構造、本当に適切?
- 正規化しすぎていないか?
- 逆に分かれすぎていないか?
- よく使う組み合わせなのに毎回JOINしていないか?
■ 中間テーブルや集約はできないか?
例えば、
- 注文+商品を毎回JOINする → 集約テーブルを持つ
- よく使うデータ → キャッシュやマテリアライズドビューを使う
■ 必要なデータは何か?
全部取ってから削るのではなく、
最初から必要なものだけ取る設計
にする。
AIが書いたSQLに注意する
最近は ChatGPT などにSQLを書かせることも増えています。
ただし、
AIは「正しいSQL」は書けるけど
「最適な設計」は保証してくれない
という点には注意が必要です。
よくあるのが、
- とにかくJOINを増やす
- とりあえず全部つなぐ
“動くけど遅いSQL”
になってしまうケースです。
もちろんAIを正しく制御すれば書いてくれることもあるでしょうけどね。
だからこそ、
人間側が設計を理解していることが重要
になります。
まとめ
- JOINは便利だが、増やしすぎるとパフォーマンスに影響する
a.id = b.a_idと JOIN は意味は近いが、JOIN構文を使うのが基本- 遅い原因はSQLではなく「設計」にあることが多い
- 必要なデータだけを取る意識が大切
SQLが遅いとき、
つい「書き方」を疑ってしまいがちですが、
本当に見るべきなのは「構造」です。
この視点を持っておくと、
SQLの見え方がかなり変わってきます。
普段から「どうやって動いているのか」「だからどう作るのか」を考えることが大切ですね。
読んでくださってありがとうございます。
それではまた!