Oracle 索引(Index)详解
Oracle 索引(Index)详解
适用版本:Oracle Database 9i / 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07
1. 概述
索引 提升查询性能[1]:
| 类型 | 说明 |
|---|---|
| B-Tree | 默认,平衡树 |
| Bitmap | 位图,低基数 |
| Reverse Key | 反转键 |
| Function-Based | 函数索引 |
| Domain | 自定义 |
| IOT | 索引组织表 |
2. B-Tree 索引
2.1 创建
-- 普通索引
CREATE INDEX idx_emp_name ON employees(last_name);
-- 复合索引
CREATE INDEX idx_emp_dept_sal ON employees(dept_id, salary);
-- 唯一索引
CREATE UNIQUE INDEX idx_emp_email ON employees(email);
2.2 结构
Root(根块)
├─ Branch(分支块)
│ ├─ Branch
│ │ ├─ Leaf(叶子块)→ 行数据 ROWID
│ │ └─ Leaf
│ └─ Branch
└─ Branch
2.3 特点
- 适合高基数列
- 支持 =, >, <, BETWEEN, LIKE(前缀)
- DML 开销中等
- 索引不存 NULL
3. Bitmap 索引
3.1 创建
CREATE BITMAP INDEX idx_emp_gender ON employees(gender);
CREATE BITMAP INDEX idx_emp_status ON employees(status);
3.2 结构
值 'M': 1010010101
值 'F': 0101101010
3.3 特点
- 适合低基数列(< 1%)
- 空间小
- 高效 AND/OR 操作
- DML 开销大
- 适合 OLAP,不适合 OLTP
4. Reverse Key 索引
CREATE INDEX idx_emp_id_rev ON employees(employee_id) REVERSE;
4.1 特点
- 反转键值(123 → 321)
- 减少热点块
- 不支持范围查询
- 适合 RAC 序列生成
5. Function-Based 索引
5.1 创建
-- 函数索引
CREATE INDEX idx_emp_upper_name ON employees(UPPER(last_name));
-- 使用
SELECT * FROM employees WHERE UPPER(last_name) = 'SMITH';
-- 表达式索引
CREATE INDEX idx_emp_sal_annual ON employees(salary * 12);
-- 使用
SELECT * FROM employees WHERE salary * 12 > 60000;
5.2 注意
- 必须启用 QUERY REWRITE
- 函数必须确定性
- 收集统计信息
6. 复合索引
6.1 列顺序
-- 好:where dept_id = 10 AND salary > 5000
CREATE INDEX idx_emp_dept_sal ON employees(dept_id, salary);
-- 等值条件在前
-- 范围条件在后
6.2 前缀扫描
-- 索引 (a, b, c)
SELECT * FROM t WHERE a = 1; -- 使用
SELECT * FROM t WHERE a = 1 AND b = 2; -- 使用
SELECT * FROM t WHERE a = 1 AND b = 2 AND c = 3; -- 使用
SELECT * FROM t WHERE b = 2; -- 不使用
SELECT * FROM t WHERE a = 1 AND c = 3; -- 部分使用
7. 索引组织表(IOT)
7.1 创建
CREATE TABLE employees_iot (
id NUMBER,
name VARCHAR2(100),
salary NUMBER,
CONSTRAINT pk_emp_iot PRIMARY KEY (id)
) ORGANIZATION INDEX;
7.2 特点
- 表数据存储在索引中
- 按主键排序
- 适合主键查询
- 节省空间
8. 索引选项
8.1 ONLINE
-- 在线创建(不阻塞 DML)
CREATE INDEX idx_emp_name ON employees(last_name) ONLINE;
8.2 PARALLEL
-- 并行创建
CREATE INDEX idx_emp_name ON employees(last_name) PARALLEL 4;
8.3 NOLOGGING
-- 不记录 redo(快)
CREATE INDEX idx_emp_name ON employees(last_name) NOLOGGING;
8.4 COMPRESS
-- 压缩
CREATE INDEX idx_emp_dept ON employees(dept_id, dept_name) COMPRESS 1;
8.5 TABLESPACE
-- 指定表空间
CREATE INDEX idx_emp_name ON employees(last_name)
TABLESPACE indx;
9. 索引维护
9.1 重建
ALTER INDEX idx_emp_name REBUILD;
ALTER INDEX idx_emp_name REBUILD ONLINE;
ALTER INDEX idx_emp_name REBUILD TABLESPACE indx;
9.2 合并
ALTER INDEX idx_emp_name COALESCE;
9.3 统计信息
EXEC DBMS_STATS.GATHER_INDEX_STATS('SCOTT', 'idx_emp_name');
9.4 监控使用
-- 启用监控
ALTER INDEX idx_emp_name MONITORING USAGE;
-- 查看
SELECT * FROM v$object_usage;
-- 停止
ALTER INDEX idx_emp_name NOMONITORING USAGE;
9.5 删除
DROP INDEX idx_emp_name;
10. 查看索引
SELECT
index_name,
index_type,
table_name,
uniqueness,
status
FROM user_indexes
WHERE table_name = 'EMPLOYEES';
-- 索引列
SELECT
index_name,
column_name,
column_position
FROM user_ind_columns
WHERE table_name = 'EMPLOYEES';
11. 索引选择
11.1 决策因素
- 数据基数
- 查询频率
- DML 频率
- 表大小
- 存储空间
11.2 选择矩阵
| 场景 | 推荐索引 |
|---|---|
| 高基数等值 | B-Tree |
| 低基数 | Bitmap |
| 序列生成 | Reverse Key |
| 函数查询 | Function-Based |
| 主键查询 | IOT |
| 范围查询 | B-Tree |
12. 何时不应建索引
- 小表
- 极少查询的列
- 高频 DML 列
- WHERE 不使用的列
- 基数极低(如布尔)
13. 常见坑与排错
13.1 索引不使用
-- 1. 函数阻止
WHERE UPPER(name) = 'SMITH' -- 索引 name 不用
-- 修复:函数索引 UPPER(name)
-- 2. 隐式转换
WHERE id = '100' -- 字符转数字,索引不用
-- 修复:WHERE id = 100
-- 3. NULL 查询
WHERE name IS NULL -- 索引不存 NULL
-- 修复:bitmap 索引 或 默认值
-- 4. 统计信息过期
EXEC DBMS_STATS.GATHER_TABLE_STATS(...);
-- 5. CBO 选择全表扫描
-- 加 HINT
SELECT /*+ INDEX(e idx_emp_name) */ * FROM employees e WHERE ...
13.2 索引碎片
-- 查看高度
ANALYZE INDEX idx_emp_name VALIDATE STRUCTURE;
SELECT height, name FROM index_stats;
-- 重建
ALTER INDEX idx_emp_name REBUILD;
13.3 ORA-01502: 索引失效
-- 原因:UNUSABLE 状态
-- 修复:重建
ALTER INDEX idx_emp_name REBUILD;
14. 最佳实践
- 主键自动建索引:默认
- 外键加索引:避免锁
- 查询频繁列建索引:性能
- 高基数用 B-Tree:标准
- 低基数用 Bitmap:OLAP
- 函数列用 FBI:避免全表扫描
- 复合索引列顺序:等值在前
- 定期维护:重建/统计
- 监控使用:删除无用
- 避免过度索引:影响 DML
15. 参考资料
[1] Oracle Database Concepts 19c, “Indexes” https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/indexes.html