0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SQL】明日からドヤ顔できる!地味だけど効く「DBの小技」5選

Posted at

【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 email
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 はパフォーマンスにも影響しません(オプティマイザが無視します)。


🎁 まとめ

  1. 重複OKなら UNION ALL で時短。
  2. 全消しなら TRUNCATE で爆速化。
  3. COUNT の NULL無視問題に注意。
  4. インデックスを活かすなら前方一致 (XXX%)。
  5. 動的SQLは WHERE 1=1 で楽をする。

どれも小さなことですが、チリも積もれば山となります。
「お、こいつDB分かってるな」と思われるエンジニアを目指しましょう!


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?