4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【DB】それ絶対ダメ。パフォーマンスを殺す「よくないインデックス」の張り方

Posted at

はじめに

以前、DBインデックスの基本と効果について記事を書いた。
しかし実務では、次のような誤解をよく見る。

「遅いなら、とりあえずインデックス貼ればよくない?」

結論から言うと、
インデックスは「付けすぎると確実にパフォーマンスを落とす」

この記事では、
「これは絶対にダメ」なインデックスの張り方を、
理由・実例・エビデンス付きでまとめる。


絶対にダメ①:使われていないインデックスを大量に貼る

❌ よくある例

CREATE INDEX idx_users_name ON users(name);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_created_at ON users(created_at);
CREATE INDEX idx_users_updated_at ON users(updated_at);

※ 実際に使われているのは email のみ。

なぜダメ?

  • INSERT / UPDATE / DELETE のたびに
    • 全インデックスを更新する必要がある
  • 読み取りは速くならないのに
    • 書き込み性能だけ確実に悪化
  • ストレージ消費増
  • オプティマイザの判断コストも増える

📉 「読まれないインデックス」は、純粋な負債

エビデンス


絶対にダメ②:SELECT条件を考えずに単体インデックスを乱立

❌ よくある例

CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_status ON orders(status);
CREATE INDEX idx_orders_created_at ON orders(created_at);

実際のクエリ:

SELECT *
FROM orders
WHERE user_id = 10
  AND status = 'paid'
ORDER BY created_at DESC;

なぜダメ?

  • MySQLは基本的に1つのインデックスしか使えない
  • 結果:
    • どれか1本しか効かない
    • 残りは無意味

本来必要なのは:

CREATE INDEX idx_orders_user_status_created
ON orders(user_id, status, created_at);

エビデンス


絶対にダメ③:カーディナリティが低いカラムに単体インデックス

❌ よくある例

CREATE INDEX idx_users_gender ON users(gender);
CREATE INDEX idx_users_is_deleted ON users(is_deleted);

gender: 男 / 女 / 未設定
is_deleted: true / false

なぜダメ?

  • 値の種類が少ない(低カーディナリティ)
  • インデックスで絞れない
  • 全件スキャンの方が速い

📌 MySQLは賢いので
インデックスを無視することすらある

エビデンス


絶対にダメ④:WHEREで使わないカラム順の複合インデックス

❌ よくある例

CREATE INDEX idx_logs_created_user
ON logs(created_at, user_id);

クエリ:

SELECT *
FROM logs
WHERE user_id = 5;

なぜダメ?

  • 複合インデックスは「左端一致」が原則
  • created_at を指定していないため
    • このインデックスは使われない

正解:

CREATE INDEX idx_logs_user_created
ON logs(user_id, created_at);

エビデンス


絶対にダメ⑤:「とりあえず」で全部 INDEX を貼る運用

❌ よくある運用

  • 機能追加のたびに
    • 「遅そうだから一旦インデックス」
  • 削除されない
  • 誰も使っているか把握していない

なぜダメ?

  • DBは「育つ」
  • クエリは「変わる」
  • インデックスは放置すると腐る

✔ 正しい運用

  • EXPLAIN を必ず見る
  • 定期的に
    • 使われていないインデックスを棚卸し
  • MySQLなら:
SHOW INDEX FROM table_name;

+ slow query log / performance_schema

エビデンス


まとめ:インデックスは「設計」であって「保険」じゃない

やってはいけない 理由
使われないインデックス 書き込み性能低下
単体インデックス乱立 効かない
低カーディナリティ 無意味
カラム順ミス 完全に無効
付けっぱなし 技術的負債

おわりに

インデックスは
「速くする魔法」ではなく「正しく使えば効く刃物」

  • 貼る前に EXPLAIN
  • 貼った後も定期的に見直す

これができると
DBが一気に「分かってるエンジニア感」出る

4
1
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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?