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