大量のデータを扱うOracle Databaseにおいて、高速な検索を実現するために重要な機能が「インデックス(索引)」です。インデックスを正しく使えば、SQLのパフォーマンスを劇的に改善できます。
本記事では、インデックスの基本概念から作成・確認・削除までを、実行例やテキスト図を用いてわかりやすく解説します。特に「インデックスが実際に使われたかどうかを確認する方法」については、実際のテーブル作成SQLも含めて詳しく紹介します。
💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
インデックスとは?
インデックスは、データベースにおける「検索用の目次」のようなものです。データを一行ずつ見ていく「全表走査(Full Table Scan)」を避け、目的のデータに素早くアクセスできるようにします。
図:インデックスのイメージ(本の目次との比較)
【書籍の目次】
─────────────
| 第1章:P1 |
| 第2章:P15 |
| 第3章:P28 |
─────────────
【Oracleインデックス】
─────────────
| emp_id = 100 → rowid AAB1... |
| emp_id = 101 → rowid AAB2... |
─────────────
インデックスのメリットと注意点
✅ メリット
- SELECTの検索速度が向上
- 結合条件やORDER BYにも効果的
- 一意性制約(PRIMARY KEY、UNIQUE)に必要
⚠️ 注意点
- DML(INSERT/UPDATE/DELETE)時にインデックス更新が走る
- 不必要なインデックスはパフォーマンス悪化や管理コスト増に
インデックスの種類
| 種類 | 説明 |
|---|---|
| B-treeインデックス | Oracleで最も基本。WHERE句の等価条件や範囲条件に最適 |
| ビットマップインデックス | カーディナリティが低い(値の種類が少ない)列に適している |
| 複合インデックス | 複数の列をまとめて1つのインデックスとして扱う |
| 関数ベースインデックス | UPPER(name)など関数を用いた検索を高速化 |
| ユニークインデックス | 重複を許さない制約(PRIMARY KEYなど)に使用 |
B-treeインデックスの構造
Oracleの標準であるB-tree(バランス木)インデックスは、以下のような3層構造になっています。
ルートブロック
↓
┌────────────┐
│ 中間(枝)ブロック │
└────┬──────┘
↓
┌────────────┐
│ リーフブロック(データキーとROWID)│
└────────────┘
リーフブロックに格納されたROWID(行ID)を使って、テーブル内のデータに直接アクセスします。
インデックスの作成方法
-- B-treeインデックス(単一列)
CREATE INDEX emp_idx ON employees(emp_id);
-- 複合インデックス
CREATE INDEX emp_name_dept_idx ON employees(emp_name, dept_id);
-- 関数ベースインデックス
CREATE INDEX emp_upper_idx ON employees(UPPER(emp_name));
インデックスの確認・削除
-- 確認
SELECT index_name, table_name FROM user_indexes;
-- 削除
DROP INDEX emp_idx;
🔍インデックスが使われているか確認する方法(実行計画付き)
SQLにインデックスが利用されたかどうかを確認するには、Oracleの「実行計画(EXPLAIN PLAN)」機能を使います。
Step1:検証用のテーブルとインデックスを作成
-- テーブル作成
CREATE TABLE test_index (
id NUMBER PRIMARY KEY,
name VARCHAR2(100),
age NUMBER
);
-- データ挿入(10万件)
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO test_index VALUES (i, 'User_' || i, MOD(i, 100));
END LOOP;
COMMIT;
END;
/
-- インデックス作成
CREATE INDEX test_index_name_idx ON test_index(name);
Step2:インデックスが使われるSQLを発行し、実行計画を確認
EXPLAIN PLAN FOR
SELECT * FROM test_index WHERE name = 'User_99999';
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
出力例
SQL> EXPLAIN PLAN FOR
2 SELECT * FROM test_index WHERE name = 'User_99999';
解析されました。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
Plan hash value: 2411497164
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 78 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TEST_INDEX | 1 | 78 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN ★ | TEST_INDEX_NAME_IDX | 1 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("NAME"='User_99999')
Note
-----
- dynamic statistics used: dynamic sampling (level=2)
18行が選択されました。
注目ポイント:
「INDEX RANGE SCAN」が表示されていれば、インデックスが利用されています。
インデックスが有効なケース・無駄なケース
| 状況 | インデックス活用の効果 |
|---|---|
| WHERE句で等価・範囲検索 | ◎ |
| 結合条件、ORDER BY句 | ◎ |
| データ件数が非常に少ないテーブル | △(全表走査が速いことも) |
| カーディナリティが極端に低い列 | ×(ビットマップなら可) |
| 頻繁に更新・削除される列 | △(更新コストが高いため) |
まとめ
| 項目 | 内容 |
|---|---|
| インデックスとは | データ検索を高速化する仕組み |
| 種類 | B-tree, ビットマップ, 関数ベース, 複合インデックスなど |
| 作成方法 | CREATE INDEX構文で簡単に作成可能 |
| 実行計画での確認方法 | EXPLAIN PLAN |
| 設計時の注意点 | 更新頻度、カーディナリティ、実行計画の確認など |
[参考]
データベース管理者ガイド – 21 索引の管理
SQL言語リファレンス – CREATE INDEX
SQL言語リファレンス – DROP INDEX

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



コメント