【Oracle設計実務】索引(インデックス)を作るべき理由と、作りすぎを避けるための設計ポイント

SQL

~性能・保守性・設計品質を両立するために知っておきたいこと~

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?


はじめに

Oracleにおけるパフォーマンス改善といえば「索引(インデックス)」の活用が定番です。
しかし現場では以下のような誤解も多く存在します。

「WHERE句に出てくる列にはとりあえず全部インデックスを貼れば良い」
「遅いならインデックスを増やせば解決するのでは?」

残念ながらこれは誤解です。索引は便利な反面、設計と運用を間違えると性能劣化の原因にもなり得ます。

本記事では以下を中心に解説します:

  • ✅ 索引を作成したほうが良い正当な理由
  • ✅ 作りすぎた場合のリスクと悪影響
  • ✅ 正しい設計・使用判断のポイント
  • ✅ 不要な索引の検出と削除手順

テキスト図付きでわかりやすく整理してお届けします。


✅ 索引(インデックス)を作るべき理由

理由①:特定の行を高速に検索できるから

Oracleでは、索引を使うことでフルスキャンせずに対象の行へ直接アクセスできます。これにより、検索時間が大幅に短縮されます。

▼ 図:索引の有無によるアクセスの違い

【索引なし】               【索引あり】
全行スキャン インデックス検索 → ROWIDで直接アクセス
────────────── ─────────────────────────────
| A001 | ... | | A001 |──┐
| A002 | ... | | A002 | ├─▶ 本体テーブルから該当行を取得
| A003 | ... | | A003 |──┘
────────────── ─────────────────────────────

👉 数万件以上のテーブルでは、全表スキャンとインデックスアクセスでは数十倍以上の差が出ることも


理由②:JOIN処理を高速化できるから

テーブル同士をJOINする際、結合キーにインデックスがあると、Oracleは効率的に結合処理を行えます。

▼ 図:結合キーに索引がある場合の結合の流れ

  orders                customers
────────────── ──────────────
| customer_id | | customer_id |
|------------| |-------------|
| C001 | ──▶ | C001 |
| C002 | ──▶ | C002 |
────────────── ──────────────
↑ ↑
結合キーに索引 結合キーに索引

👉 Nested Loop JoinやHash Joinでインデックスがある方が内側に選ばれると高速になる


理由③:ORDER BY / GROUP BYの処理も高速化できるから

インデックスは並び順を持っているため、ORDER BYGROUP BYにも効果を発揮します。

SELECT * FROM employees ORDER BY hire_date;

hire_date にインデックスがあると、Oracleは並び替え処理なしで取り出せます(Index Full Scan)。

▼ 図:SORT処理の省略イメージ

[通常]
テーブル読込 → 並び替え(SORT) → 出力

[索引あり]
インデックス順に読込 → 出力(SORT不要)

理由④:一意性制約(UNIQUE)を保証できるから

OracleではPRIMARY KEYUNIQUE制約を定義すると、自動で索引が作成されます。
これは、データの一意性を高速に検証するためです。


❗ 索引をむやみに作成するとどうなるか?

問題①:DML(INSERT/UPDATE/DELETE)が遅くなる

索引は読み取りを高速化する一方で、書き込み処理のコストを増やします

▼ 図:INSERT時の処理フロー(索引あり)

INSERT文 実行

テーブル本体に行を追加

索引1 にエントリ追加
索引2 にエントリ追加
索引3 にエントリ追加

コミット

👉 索引が増えるほど、書き込み系トランザクションの負荷が増大します。

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?


問題②:不要な実行計画を選んでしまうことがある

索引が多すぎると、Oracleのオプティマイザが誤ったインデックスを選択してしまう場合があります。

  • 結果:フルスキャンや非効率なアクセスパスを選択
  • 原因:統計情報の不備、インデックス選択の混乱

問題③:ストレージ消費・管理負荷が増える

索引も物理セグメントとして表領域を消費します。
不要な索引があると、ディスク容量・バックアップサイズも増加します。

▼ 図:テーブルと索引の関係(表領域)

+------------------+
| 表領域(USERS) |
+------------------+
| テーブル:orders |
| 索引:idx_cust |
| 索引:idx_date |
| 索引:idx_flag | ← これ不要かも?
+------------------+

✅ 正しい索引設計の考え方

作成すべき条件

用途指針
WHERE句での頻繁な検索✅ 作成を検討
結合(JOIN)キー✅ 作成を検討
ORDER BY / GROUP BY 対象列✅ 効果あり
UPDATE頻度が高い列⚠ 慎重に判断
SELECT句にのみ登場する列❌ 不要

複合索引を使う場合の注意点

複数列を対象とする複合索引は検索条件の順序が重要です。

CREATE INDEX idx_emp_dept_job ON employees(dept_id, job_id);

▼ 有効な検索

-- dept_idだけ指定 → 有効
SELECT * FROM employees WHERE dept_id = 10;

-- dept_idとjob_idを指定 → 有効
SELECT * FROM employees WHERE dept_id = 10 AND job_id = 'CLERK';

▼ 無効な検索(順序が合っていない)

-- job_idだけ指定 → 無効(索引は使われない)
SELECT * FROM employees WHERE job_id = 'CLERK';

✅ 不要な索引を見つける方法

Oracleでは、索引の使用状況をモニタリングする機能があります。

ALTER INDEX idx_orders_cust MONITORING USAGE;

-- 数日後に使用状況を確認
SELECT index_name, table_name, used
FROM v$object_usage
WHERE used = 'NO';

👉 used = 'NO' であれば、削除の検討対象になります。


まとめ:インデックス設計の基本方針

観点推奨方針
パフォーマンスWHERE句やJOIN列に必要最小限の索引を貼る
書き込み負荷INSERT/UPDATEの多い列は慎重に扱う
ストレージ効率定期的に未使用の索引を整理する
実行計画EXPLAIN PLANで効果を確認して設計する

🔚 最後に

索引は、正しく使えばOracleにおける最強の性能改善手段です。
しかし、闇雲に増やせばかえって性能を悪化させる「諸刃の剣」にもなり得ます。

「本当にそのSQLが索引を必要としているか?」
「その索引は作成後、どの程度使われているか?」

この問いを忘れず、目的に応じた設計と定期的な見直しを実践しましょう。

[参考]
Oracle Database データベース開発ガイド 19c

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?

Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?

コメント

タイトルとURLをコピーしました