【SQL】明日からドヤ顔できる!地味だけど効く「DBの小技」5選 🛠️
プロシージャ」といった少し重めの話をしてきましたが、今回は もっとライトで実用的な「小技(Tips)」 を紹介します。
SQLを書くとき、なんとなくで書いていませんか?
ほんの少し書き方を変えるだけで、実行速度が10倍になったり、バグを防げたりします。
知っておくと開発が捗る、選りすぐりの5つをピックアップしました!
1. 🏎️ UNION ではなく UNION ALL を使う
2つのテーブルの結果を合体させたいとき、無意識に UNION を使っていませんか?
-- 🐌 ちょっと遅い
SELECT name FROM users_a
UNION
SELECT name FROM users_b;
なぜダメ?
ただの UNION は、合体した後に 「重複排除(DISTINCT)」の処理が走ります。
つまり、DB内部で全データを並び替えて比較する作業が発生するため、データ量が多いと重くなります。
🚀 改善案
重複が含まれてもいい(または重複しないことが分かっている)場合は、UNION ALL を使いましょう。
こちらは「単純にくっつけるだけ」なので爆速です。
-- 🏎️ 爆速
SELECT name FROM users_a
UNION ALL
SELECT name FROM users_b;
2. 🗑️ 全件削除は DELETE ではなく TRUNCATE
テスト環境などで「テーブルの中身を空っぽにしたい」とき、どうしていますか?
-- 🐌 遅い
DELETE FROM logs;
なぜダメ?
DELETE は、 「1行ずつ削除して、その削除履歴(ログ)を残す」 という丁寧な仕事をします。100万行あれば100万回の削除処理が走ります。
🚀 改善案
TRUNCATE(トランケート)を使いましょう。
-- 🏎️ 爆速
TRUNCATE TABLE logs;
これは「テーブルごと捨てて、新品の空箱を再設置する」ような動きをするため、一瞬で終わります。
※ただし、ロールバック(取り消し)ができない場合が多いので、本番環境での使用は慎重に!
3. 👻 COUNT(*) と COUNT(カラム名) の罠
「データの件数を数えたい」とき、この2つの違いを意識していますか?
実は結果が変わる可能性があります。
-
COUNT(*): 行そのものを数えます。NULLも含みます。 -
COUNT(カラム名): そのカラムに入っている値を数えます。NULLは無視されます。
具体例
| id | name | |
|---|---|---|
| 1 | 佐藤 | sato@example.com |
| 2 | 鈴木 | NULL |
SELECT COUNT(*) FROM users; -- 結果: 2
SELECT COUNT(email) FROM users; -- 結果: 1 (鈴木さんが消えた!)
「会員数を数えて」と言われて email でカウントしてしまうと、「メアド未登録の会員」が集計漏れする事故が起きます。
基本的には COUNT(*) を使うのが安全です。
4. 🔍 LIKE 検索は「前方一致」ならインデックスが効く
検索機能を作るとき、とりあえず % で囲っていませんか?
-
%佐藤%(部分一致): 「佐藤」を含めばOK -
%佐藤(後方一致): 「佐藤」で終わればOK -
佐藤%(前方一致): 「佐藤」で始まればOK
🚀 小技
実は、「前方一致 (佐藤%)」だけはインデックス(索引)が使えます。
辞書で「『さ』から始まる言葉」を探すのは簡単(インデックスが効く)ですが、「途中に『さ』が入る言葉」を探すには、辞書を全部めくる必要がありますよね?DBも同じです。
パフォーマンスを気にするなら、要件次第ですが「前方一致」で妥協できないか検討してみてください。
5. 🏗️ 「WHERE 1=1」でクエリを構築しやすくする
これはプログラムでSQLを組み立てる(動的SQL)ときの有名なテクニックです。
検索フォームで「名前」や「年齢」が入力されたりされなかったりする場合、WHERE 句を繋げるのが面倒ですよね。
- 名前だけある場合:
WHERE name = '佐藤' - 年齢もある場合:
WHERE name = '佐藤' AND age = 20 - 何もない場合:
WHERE自体がいらない…?(この判定が面倒!)
🚀 改善案
最初に WHERE 1=1(常にTrue)を書いておきます。
SELECT * FROM users
WHERE 1=1
AND name = '佐藤' -- ここは動的に追加
AND age = 20 -- ここも動的に追加
こうすると、全ての条件を AND 〇〇 という形で統一して追加できるため、プログラムのロジックが非常にシンプルになります。
1=1 はパフォーマンスにも影響しません(オプティマイザが無視します)。
🎁 まとめ
- 重複OKなら
UNION ALLで時短。 - 全消しなら
TRUNCATEで爆速化。 -
COUNTの NULL無視問題に注意。 - インデックスを活かすなら前方一致 (
XXX%)。 - 動的SQLは
WHERE 1=1で楽をする。
どれも小さなことですが、チリも積もれば山となります。
「お、こいつDB分かってるな」と思われるエンジニアを目指しましょう!