カテゴリ: データベース 更新日: 2026/02/13

SQL複合インデックスの設計ガイド!初心者でもわかるデータベース高速化のコツ

複合インデックスとは?設計時の注意点を初心者向けに整理
複合インデックスとは?設計時の注意点を初心者向けに整理

先生と生徒の会話形式で理解しよう

生徒

「データベースからデータを探すのが遅いとき、インデックスを貼ると速くなると聞きました。でも、項目が2つ以上あるときはどうすればいいんですか?」

先生

「そんなときに使うのが『複合インデックス』です。名字と名前の両方を使って名簿から人を探すようなときに、とても役に立つ仕組みですよ。」

生徒

「複合インデックス……なんだか難しそうですね。パソコンの操作も詳しくない私にでも使いこなせますか?」

先生

「もちろんです。辞書の引き方や、整理整頓のルールを知っていれば誰でも理解できます。一つずつ順番に見ていきましょう。」

1. SQLとは何か?

1. SQLとは何か?
1. SQLとは何か?

SQLは、データベースと呼ばれる「大量のデータを整理して保存する箱」に対して指示を出すための言語です。例えば、会員名簿の中から特定の人を探したり、新しい人を追加したりするときに使います。

データベースは、例えるなら巨大な「図書館」や「倉庫」のようなものです。そこには膨大な数の本や商品(データ)が保管されています。私たちが「20代の会員だけを表示して」や「東京に住んでいる人を教えて」とお願いするときに、コンピュータが理解できる専用の言葉としてSQLを使います。

しかし、データが数百万件、数千万件と増えていくと、端から順番に探していては時間がかかってしまいます。そこで必要になるのが、検索を高速化するための「インデックス(索引)」という技術なのです。

2. インデックス(索引)の基本をおさらい

2. インデックス(索引)の基本をおさらい
2. インデックス(索引)の基本をおさらい

まず「インデックス」とは何かを簡単に説明します。皆さんは、分厚い教科書や辞書で調べものをするとき、どうしていますか? 最初のページから一枚ずつめくって探すのは大変ですよね。そのため、本の最後には「索引(さくいん)」が付いています。あいうえお順に並んだキーワードを見て、その横にあるページ番号へ直接飛ぶことで、目的の情報をすぐに見つけることができます。

データベースのインデックスもこれと同じです。特定の列(項目)に対してインデックスを作成しておくと、データベースはデータを探す手間を大幅に省くことができます。これを専門用語で「検索の最適化」や「パフォーマンス向上」と呼びます。インデックスがない状態は、バラバラになった数万枚のプリントから特定の1枚を、1枚ずつ確認して探すようなもので、非常に非効率なのです。

3. 複合インデックスとは?

3. 複合インデックスとは?
3. 複合インデックスとは?

今回の大切なテーマである「複合インデックス(マルチカラムインデックス)」とは、2つ以上の列を組み合わせて作るインデックスのことです。通常のインデックスが「名字」だけで探すためのものだとしたら、複合インデックスは「名字」と「名前」をセットにして、一つの索引として管理するイメージです。

例えば、あなたが大規模なショッピングサイトの管理をしているとしましょう。お客様のデータを「都道府県」と「年齢」で検索することが多い場合、この2つをセットにした複合インデックスを作ると、検索スピードが劇的に速くなります。

ここで、会員データが入った「customers」というテーブル(表)を見てみましょう。


id | last_name | first_name | prefecture | age
---+-----------+------------+------------+----
1  | 佐藤      | 太郎       | 東京都     | 25
2  | 鈴木      | 花子       | 大阪府     | 19
3  | 高橋      | 一郎       | 東京都     | 30
4  | 田中      | 健二       | 福岡県     | 45
5  | 伊藤      | 恵子       | 愛知県     | 22
6  | 渡辺      | 直樹       | 東京都     | 19

この表から、「東京都に住んでいる19歳の人」を探すSQLを書いてみます。


SELECT *
FROM customers
WHERE prefecture = '東京都' AND age = 19;

実行結果は以下のようになります。


id | last_name | first_name | prefecture | age
---+-----------+------------+------------+----
6  | 渡辺      | 直樹       | 東京都     | 19

複合インデックスを設定していないと、コンピュータはまず「東京都の人」を全員探し出し、その中からさらに「19歳の人」を一人ずつ確認します。しかし、「都道府県」と「年齢」の複合インデックスがあれば、ピンポイントでこのデータにたどり着けるのです。

4. 複合インデックス設計の最も重要なルール:左側優先の原則

4. 複合インデックス設計の最も重要なルール:左側優先の原則
4. 複合インデックス設計の最も重要なルール:左側優先の原則

複合インデックスを設計するときに、絶対に覚えておかなければならないルールがあります。それが「左側からの順番」です。インデックスを作るときに指定した項目の順番が、検索のときに重要になります。

例えば、「名字」と「名前」の順番で複合インデックスを作った場合、それは「名字順に並んでいて、同じ名字の中では名前順に並んでいる」という状態です。これは電話帳をイメージするとわかりやすいでしょう。

電話帳(名字・名前の順)を使って探せるのは、次のようなパターンです。

  • 「佐藤」さんを探す(最初の項目だけ指定)
  • 「佐藤 太郎」さんを探す(両方の項目を指定)

しかし、「名前が 太郎 さん」だけを指定して探そうとしても、電話帳は名字順に並んでいるため、名前だけで探すには結局最初から最後まで見なければなりません。これをデータベースの世界では「インデックスが効かない」と言います。

次のSQLコードを見てみましょう。今度は商品の注文履歴(orders)を管理するテーブルを例にします。


order_id | category | order_date | price
---------+----------+------------+------
101      | 食品     | 2024-01-01 | 1500
102      | 家電     | 2024-01-02 | 50000
103      | 食品     | 2024-01-03 | 2000
104      | 雑貨     | 2024-01-04 | 800
105      | 家電     | 2024-01-05 | 35000

もし、「category(カテゴリ)」と「order_date(注文日)」の順番で複合インデックスを作った場合、次のような検索は高速になります。


-- カテゴリと注文日の両方を指定する場合(高速!)
SELECT *
FROM orders
WHERE category = '家電' AND order_date = '2024-01-02';

しかし、次のように「注文日」だけで検索しようとすると、作成した複合インデックスはうまく使われません。


-- 注文日だけで検索する場合(このインデックスでは遅い!)
SELECT *
FROM orders
WHERE order_date = '2024-01-02';

このように、よく検索で使う項目を「左側(最初)」に持ってくるのが設計の鉄則です。

5. カーディナリティ(選択度)を意識しよう

5. カーディナリティ(選択度)を意識しよう
5. カーディナリティ(選択度)を意識しよう

初心者の方向けに、もう一つ大切な言葉を紹介します。それは「カーディナリティ」です。少し難しい言葉ですが、中身は簡単です。これは「その項目の値がどれくらいバラバラか」という度合いを指します。

例えば、「性別(男性・女性)」という項目は、種類が少ないのでカーディナリティが低いと言います。逆に、「メールアドレス」や「社員番号」は一人ひとり違うため、種類が多くカーディナリティが高いと言います。

インデックスを作るときは、この「カーディナリティが高い項目」を優先的に含めると、検索の効率が良くなります。絞り込みが強力になるからです。例えば「性別」だけで絞り込んでもデータは半分にしか減りませんが、「社員番号」で絞り込めば一気に1件まで特定できますよね。複合インデックスを設計するときは、より細かくデータを絞り込める項目を左側に配置することを検討しましょう。

6. インデックスを使いすぎることの注意点

6. インデックスを使いすぎることの注意点
6. インデックスを使いすぎることの注意点

「インデックスを作れば作るほど速くなるなら、全部の項目に作っちゃえばいいじゃない!」と思うかもしれません。しかし、そこには落とし穴があります。インデックスにはメリットだけでなく、デメリットもあるのです。

1. データの追加・更新が遅くなる
新しいデータを追加するたびに、データベースは「索引」の方も書き換えなければなりません。本に新しいページが増えるたびに、索引ページを書き直す作業を想像してください。インデックスが多すぎると、この作業に時間がかかってしまい、システム全体の動きが重くなってしまいます。

2. 保存容量(メモリやディスク)を消費する
インデックスは、それ自体がデータとして保存されます。大量に作ると、スマートフォンの写真がいっぱいになって動きが悪くなるのと同じように、データベースの容量を圧迫してしまいます。

3. メンテナンスが大変
設計が複雑になりすぎると、後から「どのインデックスが本当に必要なのか」がわからなくなってしまいます。初心者のうちは、特によく使う検索パターンに絞って、最小限のインデックスから始めるのがおすすめです。

7. 実践!複合インデックスを設計する手順

7. 実践!複合インデックスを設計する手順
7. 実践!複合インデックスを設計する手順

それでは、具体的にどのように設計を進めればよいか、ステップに分けて整理しましょう。

ステップ1:よく使われる検索条件を特定する
システムの中で、ユーザーがどのような条件で検索を行うかを調べます。「ログインIDとパスワード」「日付と店舗名」など、常にセットで使われる組み合わせを見つけます。

ステップ2:項目の順番を決める
先ほど説明した「左側優先」と「カーディナリティ」を考えます。より絞り込みが強い項目、またはその単体でも検索されることが多い項目を左側に置きます。

ステップ3:実際にSQLを試して効果を確認する
インデックスを作った前後で、どれくらい速度が変わったかを測定します。これを「ベンチマーク」と呼びます。プロの世界では、ただ作るだけでなく、必ずその効果を確認する作業を行います。

最後に、在庫管理システム(inventory)を例にした、インデックスの使い分けを見てみましょう。


item_id | warehouse_id | section_code | stock_count
--------+--------------+--------------+------------
501     | 1            | A-10         | 100
502     | 1            | B-05         | 50
503     | 2            | A-10         | 200
504     | 3            | C-01         | 10

「どの倉庫(warehouse_id)の、どの区画(section_code)に、何があるか」を頻繁に検索する場合、次のような複合インデックスを作成するのが一般的です。


-- 倉庫IDと区画コードを組み合わせたインデックスの作成例
CREATE INDEX idx_warehouse_section 
ON inventory (warehouse_id, section_code);

このように設計することで、特定の倉庫全体の在庫を確認するのも、その中の特定の区画を確認するのも、両方高速に行えるようになります。データベースの設計は、まるでパズルのように最適な組み合わせを見つける、とても奥が深く面白い作業なのです。

カテゴリの一覧へ
新着記事
New1
Ruby
Gemとは?RubyGemsとBundlerを初心者向けに完全解説!依存関係管理も図解でわかりやすく理解
New2
Ruby
Rubyの文字エンコーディング入門!UTF-8・マジックコメント・外部/内部エンコーディングを完全解説
New3
Rails
Rails GoodJob入門!PostgreSQLベースのバックグラウンド処理を初心者向けに完全解説
New4
Ruby
Rubyで学ぶビット演算入門:&・|・^・~・<<・>>の基礎と実例
人気記事
No.1
Java&Spring記事人気No1
Ruby
Rubyのreduceとinject入門!合計計算や集計を初心者向けに分かりやすく解説
No.2
Java&Spring記事人気No2
Ruby
Rubyの始め方ガイド:インストールから最初のHello Worldまで(Windows/Mac/Linux)
No.3
Java&Spring記事人気No3
Ruby
Rubyの文字列エンコーディング完全ガイド!Encoding・force_encoding・encodeを初心者向け解説
No.4
Java&Spring記事人気No4
データベース
PostgreSQLのWHERE句を徹底解説!初心者でもわかるSQLデータ抽出の基本
No.5
Java&Spring記事人気No5
Ruby
Rubyのfind/detect/find_indexを徹底解説!目的のデータを素早く探す方法
No.6
Java&Spring記事人気No6
Ruby
Rubyで比較演算子を完全解説!==・===・<=>・eql? の使い分け
No.7
Java&Spring記事人気No7
Ruby
Rubyのselect/reject/filterの使い方を完全解説!初心者向けの条件抽出レシピ
No.8
Java&Spring記事人気No8
データベース
PostgreSQLで順位付け!ROW_NUMBER関数の使い方を初心者向けに徹底解説