「検索が遅い」「JOINが重い」「ORDER BYで時間が溶ける」――その原因、インデックス不足かもしれません。
一方で、インデックスは闇雲に貼ると更新が遅くなる容量が増えるなどの副作用もあります。
この記事では、現場で役立つように「インデックス(INDEX)とは何か」から「使えるDB」「メリット・デメリット」「具体的なSQL例」「作成・確認・削除方法」まで、実用寄りでまとめます。

Contents

インデックス(INDEX)とは何か

インデックスとは、テーブルのデータを素早く見つけるための“検索用の目次”です。
本を探すときに、1ページ目から全部読むのではなく、巻末の索引(index)で目的の単語を引くのと同じ発想です。

DBはインデックスがないと、条件に合う行を探すために全件走査(フルスキャン)しがちです。
インデックスがあると、条件に合う行の位置を効率よく辿れるため、特に件数が多いテーブルほど効きます

インデックスが効きやすい典型パターン

  • WHEREで絞る(例:日付範囲、ID、ステータス)
  • JOINの結合キー(例:user_id、order_id)
  • ORDER BY / GROUP BY(並び替え・集計)
  • UNIQUE制約(重複禁止)

よくある誤解

  • インデックスを貼れば何でも速くなる → 更新が遅くなるなどの代償がある
  • たくさん貼れば最強 → 使われないインデックスは負債
  • LIKE ‘%abc%’ でも速くなる → 多くのDBで前方一致以外は効きにくい(例外あり)

インデックスが使えるDBの種類(代表例)

結論:主要なRDB(リレーショナルDB)はほぼ全てインデックス機能を持っています。

  • MySQL(InnoDB)
  • PostgreSQL
  • Microsoft SQL Server
  • Oracle Database
  • SQLite
  • MariaDB

またNoSQLでも、MongoDBやElasticsearchなどは「インデックス」に近い仕組みを持ちますが、
この記事はまずSQL系(RDB)を中心に解説します。

インデックスの主な種類(ざっくり理解でOK)

  • B-tree系:最も一般的。範囲検索(>,<,BETWEEN)や並び替えに強い
  • Hash系:等価検索(=)に強い(DBによって扱いが異なる)
  • FULLTEXT:全文検索向け(MySQL/PostgreSQLなど)
  • Spatial:地理空間(緯度経度など)向け

迷ったらまずは B-tree系の通常インデックス を基準に考えるのが実務的です。

インデックス作成のメリット(効果が出る場面)

1)WHERE検索が速くなる(最重要)

例:日付やステータスで絞る検索が多い場合、インデックスで劇的に変わります。

-- 例:受注テーブル
SELECT *
FROM orders
WHERE customer_id = 123
  AND order_date >= '2026-01-01'
  AND order_date < '2026-02-01';

このとき、次のような複合インデックス(customer_id + order_date)が有効になりやすいです。

-- MySQL / PostgreSQL(基本形)
CREATE INDEX idx_orders_customer_date
ON orders (customer_id, order_date);

2)JOINが速くなる(結合キーが重要)

JOINは「結合先を探す」動きが入るため、結合キーにインデックスがないと重くなりやすいです。

SELECT o.id, o.order_date, c.name
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.order_date >= '2026-01-01';

基本は以下を意識します。

  • 主キー(customers.id)は通常インデックスあり
  • 外部キー(orders.customer_id)にインデックスがあると強い
CREATE INDEX idx_orders_customer_id
ON orders (customer_id);

3)ORDER BY / GROUP BY が速くなることがある

並び替えや集計は、インデックスの並びを利用できると速くなる場合があります。

SELECT *
FROM orders
WHERE customer_id = 123
ORDER BY order_date DESC
LIMIT 50;
CREATE INDEX idx_orders_customer_date_desc
ON orders (customer_id, order_date);

DBによってはDESC指定をインデックスに持てる/持てない等の違いがありますが、
「絞り込み(customer_id)→並び替え(order_date)」の順に並べた複合インデックスは定番です。

4)UNIQUE制約で重複を防げる(品質が上がる)

-- メールアドレスの重複禁止など
CREATE UNIQUE INDEX ux_users_email
ON users (email);

インデックス作成のデメリット(落とし穴)

1)INSERT/UPDATE/DELETEが遅くなる

インデックスは「目次」なので、データが増減するたびに目次も更新されます。
インデックスが多いほど、更新系(書き込み)が重くなります。

2)ストレージ容量が増える

インデックスは別構造として保持されます。テーブルが巨大になるほど、インデックスも肥大化します。

3)設計を間違えると使われない(=無駄)

  • カーディナリティ(値の種類)が少なすぎる列(例:性別、フラグ)に単独インデックス
  • 関数をかけたWHERE(例:WHERE DATE(created_at) = ‘…’)でインデックスが効かない
  • LIKE ‘%abc%’ のような前方ワイルドカード
  • 複合インデックスの列順がクエリと合っていない

4)運用・保守の負債になる

使われないインデックスが増えると、更新性能を下げるだけでなく、チューニング時の判断も難しくなります。
「作った経緯が不明なインデックス」は典型的な技術的負債です。

具体的な記述例(実務でよく使うパターン)

単一インデックス(基本)

CREATE INDEX idx_orders_order_date
ON orders (order_date);

複合インデックス(超重要:列順が命)

複合インデックスは、左から順に効きます(一般に「左端一致」)。

-- (customer_id, order_date) の場合
-- 〇: customer_idで絞る
-- 〇: customer_id + order_dateで絞る
-- △/×: order_dateだけで絞る(DBと状況によるが効きづらいことが多い)
CREATE INDEX idx_orders_customer_date
ON orders (customer_id, order_date);

カバリングインデックス(取得列まで含めて“テーブルを見に行かない”狙い)

DBや状況によりますが、インデックスだけで必要な列が揃うと高速化することがあります。

-- 例:一覧表示で id と order_date だけ返すなら
CREATE INDEX idx_orders_customer_date_id
ON orders (customer_id, order_date, id);

部分(条件付き)インデックス(PostgreSQLなど)

「特定条件だけ頻繁に検索する」なら、対象を絞ったインデックスが効くことがあります。

-- PostgreSQL例:有効ユーザーだけ
CREATE INDEX idx_users_active_email
ON users (email)
WHERE is_active = true;

関数インデックス(DBによる)

「関数をかけるから効かない」を回避するために、DBによっては式/関数のインデックスが作れます。

-- PostgreSQL例:lower(email) で検索する運用なら
CREATE INDEX idx_users_lower_email
ON users (lower(email));

インデックスの作成・確認・削除方法(DB別)

MySQL / MariaDB

作成

CREATE INDEX idx_orders_customer_id
ON orders (customer_id);

CREATE UNIQUE INDEX ux_users_email
ON users (email);

確認

SHOW INDEX FROM orders;

削除

DROP INDEX idx_orders_customer_id ON orders;

PostgreSQL

作成

CREATE INDEX idx_orders_customer_id
ON orders (customer_id);

CREATE UNIQUE INDEX ux_users_email
ON users (email);

確認

-- 一覧
SELECT schemaname, tablename, indexname, indexdef
FROM pg_indexes
WHERE tablename = 'orders';

-- あるテーブルの詳細(psql)
-- \d orders

削除

DROP INDEX idx_orders_customer_id;

SQL Server

作成

CREATE INDEX idx_orders_customer_id
ON dbo.orders (customer_id);

CREATE UNIQUE INDEX ux_users_email
ON dbo.users (email);

確認

SELECT i.name, i.type_desc
FROM sys.indexes i
WHERE i.object_id = OBJECT_ID('dbo.orders');

削除

DROP INDEX idx_orders_customer_id ON dbo.orders;

Oracle

作成

CREATE INDEX idx_orders_customer_id
ON orders (customer_id);

CREATE UNIQUE INDEX ux_users_email
ON users (email);

確認

SELECT index_name, table_name
FROM user_indexes
WHERE table_name = 'ORDERS';

削除

DROP INDEX idx_orders_customer_id;

SQLite

作成

CREATE INDEX idx_orders_customer_id
ON orders (customer_id);

確認

-- インデックス一覧
PRAGMA index_list('orders');

-- 定義確認
SELECT sql
FROM sqlite_master
WHERE type = 'index' AND name = 'idx_orders_customer_id';

削除

DROP INDEX idx_orders_customer_id;

「本当に効いてる?」を確認する:実務のチェック手順

1)まずは実行計画(EXPLAIN)を見る

インデックス設計は“体感”ではなく、実行計画で判断するのが近道です。

-- MySQL / PostgreSQL
EXPLAIN
SELECT *
FROM orders
WHERE customer_id = 123
  AND order_date >= '2026-01-01';

ポイントは次のようなイメージです。

  • フルスキャン(全件)っぽい動きになっていないか
  • 狙ったインデックスが使われているか
  • 見積行数が不自然に大きくないか

2)“使われないインデックス”を増やさない

  • 似たインデックスの重複(例: (a) と (a,b) の両方)
  • 昔の機能の名残
  • クエリが変わって役に立っていない

インデックスは「作って終わり」ではなく、使われ方に合わせて見直す資産です。

失敗しないインデックス設計のコツ(実用チェックリスト)

  • WHERE / JOIN / ORDER BY を頻出順に棚卸しする
  • 大きいテーブルから優先(件数が少ないと差が出にくい)
  • 複合インデックスは列順をクエリに合わせる(絞り込み→範囲→並び替えの順が多い)
  • 更新が多いテーブルは貼りすぎ注意(更新性能と相談)
  • 関数をWHEREにかけない設計(または関数インデックス/生成列を検討)
  • 「LIKE ‘%xxx%’」は全文検索や別方式も検討(FULLTEXTなど)

まとめ:インデックスは“速さ”と“重さ”のトレードオフ

インデックス(INDEX)は、DBの検索やJOINを速くする最重要のチューニング要素です。
ただし貼りすぎると、更新が遅くなり容量も増え、保守負債にもなります。

  • 遅いクエリはまず EXPLAIN を見る
  • 効かせたいWHERE/JOINに合わせて 最小限のインデックス を貼る
  • “作って終わり”にせず、運用で見直す

「データベース インデックス」で迷ったら、この記事の手順どおりに
クエリ棚卸し → EXPLAIN → 必要な列にインデックスの順で進めるのが、最短ルートです。

 
※参考にされる場合は自己責任でお願いします。

この記事の運営者(IT部長)からのお知らせ

PCトラブルは解決しましたか?

もし「会社のPCが全部遅い」「Office 365のエラーが多発する」「ネットワークが不安定」といった、調べても解決しない「会社全体」のお悩みがありましたら、ぜひご相談ください。

「Windows11 高速化」といったお悩み検索で毎月1,200人以上が訪れる、
このサイトの運営者
(建設会社IT部長)が、川崎・横浜・東京城南エリアの法人様限定で「無料ITお困りごと診断」を行っています。