数据库索引使用总结

数据库索引是提高查询性能的关键,但如果不正确使用,反而会拖慢整体性能。本文将总结数据库索引的使用场景、不适用的情况以及导致索引失效的常见原因。

什么时候需要创建索引?

索引并非万能,但在以下场景中,创建索引能带来巨大的性能提升:

  1. 频繁作为查询条件的字段
    WHERE 子句中经常用到的字段,特别是数据量大的表中,创建索引是首选。这能让数据库从“全表扫描”变为“索引查找”,速度提升可能是数量级的。

  2. 主键字段
    数据库会自动为主键创建唯一索引,这不仅保证了记录的唯一性,也使得通过主键查找记录的速度极快。

  3. 用于表连接(JOIN)的字段
    JOIN 操作中,连接字段(通常是外键)的匹配效率至关重要。为这些字段创建索引,可以显著加速多表查询。

  4. 需要排序(ORDER BY)的字段
    当查询结果需要按某个字段排序时,如果该字段有索引,数据库可以利用索引本身有序的特性,避免额外的排序操作,从而提高效率。

  5. 需要分组(GROUP BY)的字段
    与排序类似,对分组字段创建索引,可以帮助数据库更快地找到相同值的记录,优化分组统计的性能。

  6. 需要对字段进行 DISTINCT 操作
    DISTINCT 操作的本质是去重,这与 GROUP BY 非常相似。为 DISTINCT 字段创建索引,可以利用索引的有序性来快速识别和提取唯一值,避免全表扫描。

  7. 需要保证唯一性的字段
    除了主键外,如果业务上要求某个字段(如用户邮箱、手机号)的值是唯一的,可以为其创建唯一索引(Unique Index),数据库会自动拒绝重复值的插入。

什么时候不需要创建索引?

滥用索引会占用磁盘空间,并降低写操作(INSERT, UPDATE, DELETE)的性能。以下情况应避免创建索引:

  1. 表记录太少
    对于只有几百条记录的小表,全表扫描的成本已经很低,甚至可能比查找索引更快。此时创建索引没有必要。

  2. 数据重复度高、选择性低的字段
    像“性别”、“状态”这类字段,其可能的值非常有限(例如,男/女,启用/禁用)。为这类字段创建索引,索引的“区分度”很低,查询时仍然需要扫描大量数据,无法有效提升性能。

  3. 经常被修改的字段
    索引并非没有代价。每次对表进行增、删、改操作时,相关的索引也需要同步更新。如果一个字段不常用于查询,但修改操作非常频繁,那么维护索引的开销可能会超过查询带来的收益。

  4. 不作为查询条件的字段
    如果一个字段从未或极少出现在 WHEREJOINORDER BY 子句中,那么为它创建索引纯属浪费存储空间和计算资源。

哪些情况下索引会失效?

精心创建的索引,有时却在查询中“失踪”,这就是索引失效。以下是几种常见的“索引杀手”:

  1. 在索引列上进行计算或使用函数
    这是最常见的问题。例如 WHERE age + 1 = 30WHERE LEFT(name, 3) = 'abc',优化器无法直接使用 agename 字段的索引。
    正确做法:将计算和函数操作移到等号右侧,例如 WHERE age = 30 - 1

  2. 使用 LIKE 且以通配符 % 开头
    查询 WHERE name LIKE '%关键词' 会导致索引失效,因为索引的 B-Tree 结构是按前缀排序的,无法处理前缀不确定的情况。
    正确做法:尽量使用后缀匹配,如 WHERE name LIKE '关键词%',这样可以正常使用索引。

  3. 查询条件中使用 OR
    如果 OR 连接的条件中,有一个列没有索引,那么整个查询的索引都可能失效,优化器会选择全表扫描。
    正确做法:确保 OR 两边的列都有索引,或者考虑将查询拆分为两个 UNION ALL 查询。

  4. 查询条件中存在类型转换
    如果字段 phoneVARCHAR 类型,但查询时写成 WHERE phone = 13800000000(数字类型),数据库会进行隐式类型转换,这可能导致索引失效。
    正确做法:保证查询条件中的数据类型与字段类型一致,如 WHERE phone = '13800000000'

  5. 联合索引未使用最左前缀
    对于一个由 (col1, col2, col3) 组成的联合索引,查询必须从最左边的列开始使用。如果查询条件是 WHERE col2 = 'b'WHERE col3 = 'c',则无法利用该索引。
    正确做法:查询条件应遵循最左前缀原则,例如 WHERE col1 = 'a'WHERE col1 = 'a' AND col2 = 'b'

  6. 使用 !=<> 操作符
    不等于操作符通常会让优化器放弃使用索引,转而进行全表扫描,因为其选择性较低。

总结

索引是一把双刃剑。合理地使用索引是数据库性能优化的核心技能之一。在创建索引之前,务必充分理解业务查询场景,并注意避免上述导致索引失效的“坑”,才能让索引发挥其最大价值。