Oracle 函数索引详解

Oracle 函数索引详解

适用版本:Oracle Database 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

函数索引(Function-Based Index)在函数表达式上建索引[1]:

详细见:Oracle 索引优化策略


2. 创建

2.1 基本

CREATE INDEX idx_upper_name ON employees (UPPER(name));
CREATE INDEX idx_sal_year ON sales (EXTRACT(YEAR FROM sale_date));
CREATE INDEX idx_full_name ON employees (first_name || ' ' || last_name);

2.2 复合

CREATE INDEX idx_complex ON employees (UPPER(name), dept_id);

2.3 条件

CREATE INDEX idx_active ON employees (CASE WHEN status = 'ACTIVE' THEN id END);

3. 使用

3.1 查询匹配

-- 必须 EXACT 匹配
SELECT * FROM employees WHERE UPPER(name) = 'ALICE';
-- 使用索引

SELECT * FROM employees WHERE name = 'Alice';
-- 不使用函数索引

3.2 案例

-- 大小写不敏感
SELECT * FROM employees WHERE UPPER(name) = 'ALICE';

-- 计算
SELECT * FROM sales WHERE EXTRACT(YEAR FROM sale_date) = 2025;

4. 约束

4.1 函数确定性

-- 函数必须 DETERMINISTIC
CREATE OR REPLACE FUNCTION my_func(p VARCHAR2) RETURN VARCHAR2
  DETERMINISTIC IS
BEGIN
  RETURN UPPER(p);
END;
/

4.2 查询改写

ALTER SYSTEM SET query_rewrite_enabled = TRUE;
ALTER SYSTEM SET query_rewrite_integrity = trusted;

5. 统计

5.1 收集

EXEC DBMS_STATS.GATHER_TABLE_STATS(
  'SCOTT', 'EMP',
  method_opt => 'FOR ALL HIDDEN COLUMNS SIZE 254'
);

5.2 扩展统计

-- 扩展统计匹配
SELECT DBMS_STATS.CREATE_EXTENDED_STATS('SCOTT', 'EMP', '(UPPER(name))') 
FROM dual;

详细见:Oracle 扩展统计详解


6. 应用场景

6.1 大小写

-- 大小写不敏感查询
CREATE INDEX idx_upper_email ON users (UPPER(email));
SELECT * FROM users WHERE UPPER(email) = '[email protected]';

6.2 日期

-- 按年查询
CREATE INDEX idx_year ON sales (EXTRACT(YEAR FROM sale_date));
SELECT * FROM sales WHERE EXTRACT(YEAR FROM sale_date) = 2025;

6.3 计算

-- 计算列
CREATE INDEX idx_total ON orders (qty * price);
SELECT * FROM orders WHERE qty * price > 1000;

6.4 条件

-- 部分索引
CREATE INDEX idx_active ON emp (id) WHERE status = 'ACTIVE';
-- 12c+ 部分

7. 优势

7.1 优化

- 函数查询使用索引
- 避免 FULL TABLE SCAN
- 性能提升

7.2 灵活

- 复杂表达式
- 业务逻辑
- 索引

8. 限制

8.1 DETERMINISTIC

- 函数必须确定性
- 相同输入相同输出

8.2 匹配

- 查询必须 EXACT 匹配
- 函数 + 参数

8.3 维护

- DML 开销
- 索引维护
- 监控

9. 查看

9.1 视图

SELECT index_name, index_type, funcidx_status
FROM user_indexes
WHERE index_type LIKE 'FUNCTION-BASED%';

SELECT * FROM user_ind_expressions
WHERE table_name = 'EMP';

9.2 列

SELECT column_name, data_type
FROM user_tab_cols
WHERE table_name = 'EMP'
  AND hidden_column = 'YES';

10. 性能

10.1 优势

- 函数查询加速
- 减少全表扫描

10.2 开销

- DML 时计算
- 索引维护
- 监控

11. 监控

11.1 使用

ALTER INDEX idx_upper_name MONITORING USAGE;
SELECT * FROM v$object_usage;

11.2 性能

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id'));

12. 常见问题

12.1 不使用

- 函数不匹配
- DETERMINISTIC
- query_rewrite

12.2 ORA-30553

- 函数非确定性
- DETERMINISTIC

12.3 性能

- DML 开销
- 监控
- 评估

13. 最佳实践

  1. DETERMINISTIC:必须
  2. 查询改写:启用
  3. 统计:HIDDEN 列
  4. 匹配:查询
  5. 测试:使用
  6. 监控:使用
  7. DML 评估:开销
  8. 复合:组合
  9. 文档:设计
  10. 演练:定期

14. 参考资料

[1] Oracle Database SQL Tuning Guide 19c, “Function-Based Indexes” https://docs.oracle.com/en/database/oracle/oracle-database/19/tgsql/