Skip to content

Oracle 索引优化

索引基础

索引类型

  • B-tree 索引:最常用的索引类型,适用于等值查询和范围查询
  • 位图索引:适用于低基数列,如性别、状态等
  • 函数索引:基于函数或表达式创建的索引
  • 分区索引:与分区表配合使用的索引
  • 反向键索引:适用于序列生成的主键,避免热点块
  • 位图连接索引:基于多表连接创建的索引
  • 域索引:用于文本、空间数据等特殊数据类型

索引结构

  • B-tree 结构:平衡树结构,由根节点、分支节点和叶节点组成
  • 索引条目:包含索引键值和指向数据行的 ROWID
  • 索引高度:索引的层数,影响查询性能
  • 聚簇因子:衡量索引与表数据的物理排序一致性

索引原理

  • 索引查找:通过索引快速定位数据行
  • 索引扫描类型:全索引扫描、范围扫描、唯一扫描、快速全索引扫描
  • 索引与排序:利用索引避免排序操作
  • 索引与分区:分区索引的维护和使用

索引设计

设计原则

  • 选择性原则:为选择性高的列创建索引
  • 前缀原则:考虑复合索引的列顺序,将选择性高的列放在前面
  • 覆盖原则:设计覆盖查询的索引,减少回表操作
  • 最小化原则:只创建必要的索引,避免过度索引
  • 维护成本原则:考虑索引的维护成本,特别是在高 DML 操作的表上

适合创建索引的场景

  • 频繁查询的列:WHERE 子句中经常使用的列
  • 连接条件列:多表连接时使用的列
  • 排序分组列:ORDER BY、GROUP BY 子句中使用的列
  • 唯一性约束:需要保证数据唯一性的列
  • 外键列:关联其他表的外键列

不适合创建索引的场景

  • 低选择性列:如性别、状态等只有少数几个值的列
  • 频繁更新的列:会增加索引维护成本
  • 小表:表数据量小,全表扫描可能比索引扫描更快
  • TEXT、LOB 等大字段:索引效果不明显,维护成本高
  • 频繁进行全表扫描的表:如果查询经常需要全表扫描,索引可能无用

索引使用

索引扫描类型

  • 唯一索引扫描:针对唯一索引的等值查询
  • 范围扫描:针对索引的范围查询
  • 全索引扫描:扫描整个索引,适用于需要排序或聚合的查询
  • 快速全索引扫描:并行扫描索引,适用于不需要排序的查询
  • 索引跳跃扫描:针对复合索引的优化扫描方式

索引提示

  • INDEX 提示:指定使用特定的索引
  • NO_INDEX 提示:指定不使用特定的索引
  • INDEX_ASC/DESC 提示:指定索引的扫描方向
  • INDEX_COMBINE 提示:指定使用多个索引的组合

索引使用监控

  • V$OBJECT_USAGE:监控索引的使用情况
  • 索引使用统计:收集索引的使用频率和效率
  • 执行计划分析:分析 SQL 执行计划,查看索引使用情况
  • AWR 报告:查看 Top SQL 的索引使用情况

索引维护

索引重建

  • 重建原因:索引碎片过多,性能下降
  • 重建时机:索引高度过高,删除率超过 20%
  • 重建方法:使用 ALTER INDEX REBUILD 命令
  • 在线重建:使用 ONLINE 选项,减少停机时间
  • 并行重建:使用 PARALLEL 选项,加快重建速度

索引收缩

  • 收缩原因:索引碎片过多,但不需要完全重建
  • 收缩方法:使用 ALTER INDEX SHRINK SPACE 命令
  • 收缩优势:比重建更快,产生的 redo 更少

索引监控与统计

  • 统计信息收集:定期收集索引的统计信息
  • 碎片监控:监控索引碎片情况
  • 使用情况监控:监控索引的使用频率
  • 性能监控:监控索引对查询性能的影响

索引分区维护

  • 分区索引重建:重建单个分区的索引
  • 分区索引分裂:在表分区分裂时维护索引
  • 分区索引合并:在表分区合并时维护索引
  • 分区索引删除:删除不需要的分区索引

索引优化

SQL 优化与索引

  • WHERE 子句优化:确保 WHERE 子句中的列使用索引
  • 避免索引失效:避免在索引列上使用函数、表达式等
  • 复合索引顺序:合理安排复合索引的列顺序
  • 索引覆盖查询:设计查询使其使用索引覆盖

索引压缩

  • 压缩原因:减少索引占用的存储空间
  • 压缩方法:使用 COMPRESS 选项创建压缩索引
  • 压缩级别:根据实际情况选择合适的压缩级别
  • 压缩效果:减少 I/O,提高缓存命中率

索引并行度

  • 并行创建:使用 PARALLEL 选项并行创建索引
  • 并行重建:使用 PARALLEL 选项并行重建索引
  • 并行扫描:启用索引的并行扫描
  • 并行度选择:根据系统资源选择合适的并行度

索引与分区表

  • 本地分区索引:与表分区一一对应的索引
  • 全局分区索引:跨越多个表分区的索引
  • 分区索引选择:根据查询模式选择合适的分区索引类型
  • 分区索引维护:分区表维护时的索引处理

索引问题诊断

索引失效

  • 失效原因:索引列上使用函数、类型转换、IS NULL 等
  • 失效检测:通过执行计划分析发现索引失效
  • 失效解决:重写 SQL,使用函数索引等方法解决

索引过度使用

  • 过度使用症状:过多的索引导致 DML 操作变慢
  • 检测方法:分析表上的索引数量和使用情况
  • 解决方法:删除不使用的索引,合并功能相似的索引

索引碎片

  • 碎片原因:频繁的删除和更新操作
  • 碎片检测:使用 INDEX_STATS 视图检测碎片
  • 碎片解决:重建或收缩索引

索引统计信息过期

  • 过期原因:表数据发生较大变化
  • 过期检测:检查统计信息的收集时间
  • 解决方法:重新收集统计信息

索引最佳实践

复合索引设计

  • 列顺序:将选择性高的列放在前面
  • 前缀使用:确保查询能使用索引的前缀
  • 覆盖查询:设计能覆盖常见查询的复合索引
  • 避免冗余:避免创建与现有索引功能重复的复合索引

索引与数据类型

  • 数据类型选择:选择合适的数据类型,提高索引效率
  • 类型一致性:确保查询中的数据类型与索引列一致
  • 字符集考虑:考虑字符集对索引大小和性能的影响

索引与分区策略

  • 分区键选择:选择合适的分区键,与索引设计配合
  • 分区索引类型:根据查询模式选择本地或全局分区索引
  • 分区维护:定期维护分区,保持索引性能

索引监控与管理

  • 建立索引监控机制:定期检查索引使用情况
  • 建立索引生命周期管理:对索引进行创建、使用、维护和删除的全生命周期管理
  • 自动化索引管理:使用脚本自动化索引的监控和维护

常见问题(FAQ)

Q1: 如何判断 Oracle 数据库中的索引是否被使用?

A1: 可以通过以下方法判断索引是否被使用:

  • 使用 V$OBJECT_USAGE 视图监控索引使用情况
  • 启用索引监控:ALTER INDEX index_name MONITORING USAGE
  • 分析 AWR 报告中的 SQL 执行计划
  • 使用 Oracle Enterprise Manager 监控索引使用情况
  • 检查索引的访问统计信息

Q2: 复合索引的列顺序如何影响查询性能?

A2: 复合索引的列顺序对查询性能有重要影响:

  • 查询条件中使用索引的前缀列时,才能使用该复合索引
  • 将选择性高的列放在前面,可以减少索引扫描的范围
  • 对于 ORDER BY、GROUP BY 操作,复合索引的列顺序应与语句中的顺序一致
  • 覆盖查询时,复合索引的列顺序应包含查询所需的所有列

Q3: 如何解决 Oracle 索引碎片问题?

A3: 解决索引碎片问题的方法:

  • 重建索引:使用 ALTER INDEX index_name REBUILD [ONLINE] 命令
  • 收缩索引:使用 ALTER INDEX index_name SHRINK SPACE 命令
  • 在线重建:使用 ONLINE 选项,减少对业务的影响
  • 并行重建:使用 PARALLEL 选项,加快重建速度
  • 定期维护:建立索引维护计划,定期检查和处理碎片

Q4: 什么情况下应该使用位图索引?

A4: 位图索引适用于以下情况:

  • 低基数列:列值数量较少,如性别、状态等
  • 数据仓库环境:OLAP 系统,以查询为主,DML 操作较少
  • 复杂查询:需要进行多列组合查询的场景
  • 星型模型:维度表的连接列

位图索引不适合以下情况:

  • 高基数列:列值数量较多的列
  • OLTP 环境:DML 操作频繁的系统
  • 频繁更新的列:会导致位图索引维护成本高

Q5: 如何优化 Oracle 数据库中的索引以提高查询性能?

A5: 优化索引提高查询性能的方法:

  • 合理设计索引:根据查询模式设计合适的索引
  • 使用覆盖索引:设计能覆盖查询的索引,减少回表操作
  • 优化复合索引顺序:将选择性高的列放在前面
  • 定期维护索引:重建或收缩有碎片的索引
  • 收集统计信息:确保索引统计信息准确
  • 避免索引失效:避免在索引列上使用函数、类型转换等
  • 监控索引使用情况:删除不使用的索引,减少维护成本
  • 考虑分区索引:对于大表,使用分区索引提高性能