Skip to content

DM 索引设计原则

索引的作用

  • 提高查询性能:减少数据扫描范围,加快查询速度
  • 加速排序和分组:避免全表排序,提高ORDER BY和GROUP BY操作的性能
  • 保证数据唯一性:通过唯一索引确保数据完整性
  • 加速表连接:提高多表连接查询的性能

索引的开销

  • 存储空间:索引需要占用额外的存储空间
  • DML操作性能:INSERT、UPDATE、DELETE操作需要维护索引,会增加操作时间
  • 索引维护:需要定期重建或重组索引,以保持索引效率

索引类型

DM数据库支持多种索引类型,每种索引类型适用于不同的场景。

B树索引

特点

  • 最常用的索引类型
  • 适用于等值查询、范围查询和排序操作
  • 支持单列索引和复合索引
  • 索引大小随数据量增长而增长

适用场景

  • 高基数列(不同值较多的列)
  • 频繁用于WHERE条件的列
  • 用于ORDER BY或GROUP BY的列
  • 用于连接查询的列

创建示例

sql
-- 单列B树索引
CREATE INDEX idx_emp_deptno ON emp(deptno);

-- 复合B树索引
CREATE INDEX idx_emp_deptno_ename ON emp(deptno, ename);

-- 唯一B树索引
CREATE UNIQUE INDEX idx_emp_empno ON emp(empno);

位图索引

特点

  • 适用于低基数列(不同值较少的列)
  • 存储空间小,查询效率高
  • 不适合频繁更新的列

适用场景

  • 性别、状态等低基数列
  • 数据仓库环境
  • 只读或很少更新的表

创建示例

sql
-- 创建位图索引
CREATE BITMAP INDEX idx_emp_gender ON emp(gender);

函数索引

特点

  • 基于函数或表达式的结果创建索引
  • 适用于频繁使用函数或表达式的查询
  • 支持自定义函数

适用场景

  • 频繁使用函数的查询条件
  • 日期函数、字符串函数等

创建示例

sql
-- 基于函数的索引
CREATE INDEX idx_emp_hire_year ON emp(YEAR(hiredate));

-- 基于表达式的索引
CREATE INDEX idx_emp_salary_bonus ON emp(salary + NVL(bonus, 0));

全文索引

特点

  • 用于全文检索
  • 支持中文分词
  • 适用于大文本字段

适用场景

  • 文章内容、产品描述等大文本字段
  • 需要进行全文检索的场景

创建示例

sql
-- 创建全文索引
CREATE FULLTEXT INDEX idx_article_content ON article(content);

空间索引

特点

  • 用于空间数据类型
  • 支持空间查询
  • 适用于地理位置数据

适用场景

  • 地理位置数据
  • 地图应用
  • 空间分析

创建示例

sql
-- 创建空间索引
CREATE SPATIAL INDEX idx_location_coords ON location(coords);

索引设计原则

1. 只为必要的列创建索引

  • 只为经常出现在WHERE子句、ORDER BY、GROUP BY或连接条件中的列创建索引
  • 避免为很少使用的列创建索引
  • 避免为数据量很小的表创建索引

2. 考虑列的基数

  • 高基数列(不同值较多)适合创建B树索引
  • 低基数列(不同值较少)适合创建位图索引
  • 对于介于两者之间的列,需要根据具体情况选择

3. 合理选择复合索引的列顺序

  • 将选择性高的列放在复合索引的前面
  • 将经常用于等值查询的列放在前面
  • 将用于范围查询的列放在后面
  • 考虑查询中最常用的列组合

4. 避免过度索引

  • 每个表的索引数量应控制在合理范围内(通常不超过5-10个)
  • 过多的索引会影响DML操作性能
  • 会增加存储空间占用和索引维护开销

5. 为外键创建索引

  • 外键列应创建索引,以提高连接查询性能
  • 避免外键列上的全表扫描
  • 有助于避免级联删除时的锁等待

6. 考虑索引覆盖

  • 尽量让查询只通过索引就能获取所需数据
  • 减少回表操作,提高查询性能
  • 适用于频繁查询的小结果集

7. 避免在索引列上使用函数

  • 索引列上使用函数会导致索引失效
  • 考虑使用函数索引替代
  • 或者在应用层进行函数处理

8. 考虑索引的存储位置

  • 将索引存储在与数据文件不同的磁盘上,提高IO并行度
  • 考虑使用独立的表空间存储索引

9. 定期维护索引

  • 定期重建或重组索引,以保持索引效率
  • 监控索引碎片情况
  • 根据索引使用情况调整索引策略

10. 考虑数据分布

  • 了解数据的分布情况,选择合适的索引类型
  • 对于倾斜数据,考虑使用分区表和分区索引

索引设计最佳实践

1. 分析查询模式

  • 收集并分析SQL语句的执行情况
  • 识别高频查询和性能瓶颈
  • 根据查询模式设计索引

2. 使用EXPLAIN计划分析

  • 使用EXPLAIN语句分析SQL执行计划
  • 确认索引是否被有效使用
  • 调整索引设计以优化执行计划

3. 考虑数据更新频率

  • 对于频繁更新的表,减少索引数量
  • 避免在频繁更新的列上创建索引
  • 考虑使用延迟索引维护

4. 合理设置索引参数

  • 根据表的大小和查询模式设置合适的索引参数
  • 考虑索引块大小、填充因子等

5. 测试索引效果

  • 在测试环境中测试索引效果
  • 比较索引创建前后的性能差异
  • 验证索引是否满足预期

6. 考虑分区表索引

  • 对于大表,考虑使用分区表和分区索引
  • 提高查询性能和维护效率
  • 便于数据管理和归档

7. 监控索引使用情况

  • 定期监控索引的使用情况
  • 识别未使用或很少使用的索引
  • 及时删除无用索引

索引设计误区

1. 为每个列创建索引

问题:过多的索引会影响DML操作性能,增加存储空间占用。 解决方法:只为必要的列创建索引,根据查询模式选择合适的索引列。

2. 复合索引列顺序不当

问题:复合索引的列顺序会影响索引的使用效果。 解决方法:将选择性高的列放在前面,考虑查询中最常用的列组合。

3. 忽略索引维护

问题:索引会随着数据的更新而产生碎片,影响查询性能。 解决方法:定期重建或重组索引,监控索引碎片情况。

4. 在频繁更新的列上创建位图索引

问题:位图索引不适合频繁更新的列,会导致锁竞争和性能问题。 解决方法:对于频繁更新的列,使用B树索引;对于低基数列,考虑业务场景是否适合使用位图索引。

5. 索引列上使用函数

问题:索引列上使用函数会导致索引失效,无法使用索引进行查询。 解决方法:使用函数索引替代,或者在应用层进行函数处理。

6. 忽略索引覆盖

问题:查询需要回表获取数据,增加IO开销。 解决方法:设计覆盖索引,让查询只通过索引就能获取所需数据。

7. 不考虑数据分布

问题:对于倾斜数据,普通索引可能无法达到预期效果。 解决方法:考虑使用分区表和分区索引,或者调整索引设计。

版本差异说明

版本主要变化
DM 7支持B树索引、位图索引、函数索引
DM 8增强了索引功能,支持全文索引、空间索引
DM 8.1优化了索引性能,支持更多索引类型和参数配置

常见问题(FAQ)

Q1: 如何确定是否需要创建索引?

A1: 可以通过以下方法确定是否需要创建索引:

  • 分析SQL查询的执行频率和性能要求
  • 使用EXPLAIN计划分析查询性能
  • 考虑列的基数和数据分布
  • 评估索引的维护成本

Q2: 一个表应该创建多少个索引?

A2: 没有固定的答案,取决于表的大小、查询模式和更新频率。一般来说:

  • 小型表(<10万行):1-3个索引
  • 中型表(10万-100万行):3-5个索引
  • 大型表(>100万行):5-10个索引

Q3: 复合索引的列顺序如何确定?

A3: 复合索引的列顺序应考虑以下因素:

  • 列的选择性(不同值的数量)
  • 查询中最常用的列组合
  • 等值查询和范围查询的顺序
  • 排序和分组的需求

Q4: 如何判断索引是否被有效使用?

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

  • 使用EXPLAIN计划分析查询执行计划
  • 监控索引的使用情况(通过V$INDEX_USAGE视图)
  • 比较索引创建前后的查询性能

Q5: 何时应该重建或重组索引?

A5: 以下情况应该考虑重建或重组索引:

  • 索引碎片率超过20%
  • 索引查询性能明显下降
  • 大量数据被删除或更新
  • 定期维护(如每月或每季度)

Q6: 如何处理倾斜数据的索引设计?

A6: 处理倾斜数据的索引设计可以考虑以下方法:

  • 使用分区表和分区索引
  • 调整索引列顺序
  • 使用局部索引
  • 考虑使用反向索引

Q7: 函数索引和普通索引有什么区别?

A7: 函数索引和普通索引的主要区别:

  • 普通索引基于列的值创建,函数索引基于函数或表达式的结果创建
  • 普通索引适合直接查询列值,函数索引适合查询函数或表达式的结果
  • 函数索引的维护成本更高

Q8: 位图索引适合什么场景?

A8: 位图索引适合以下场景:

  • 低基数列(不同值较少的列)
  • 数据仓库环境
  • 只读或很少更新的表
  • 复杂的多条件查询

Q9: 如何删除无用的索引?

A9: 删除无用索引的步骤:

  1. 监控索引的使用情况
  2. 识别未使用或很少使用的索引
  3. 在测试环境中验证删除索引的影响
  4. 在生产环境中删除无用索引

Q10: 索引设计需要考虑哪些因素?

A10: 索引设计需要考虑以下因素:

  • 查询模式和频率
  • 数据分布和基数
  • 数据更新频率
  • 表的大小
  • 系统资源(CPU、内存、磁盘)
  • 业务需求和性能要求

索引设计是一个持续优化的过程,需要不断分析和调整,以适应业务和数据的变化。通过遵循索引设计原则和最佳实践,可以有效地提高数据库查询性能,降低系统资源消耗,为业务提供高效、稳定的数据库服务。