一、InnoDB 索引类型

1. 主键索引(PRIMARY KEY)

  • 每个 InnoDB 表必须有一个主键,没有则会自动创建一个隐藏主键。
  • 主键索引是聚簇索引(Clustered Index),索引的叶子节点存储整行数据
  • 主键索引决定了数据在物理页上的存储顺序。

2. 辅助索引(Secondary Index)

  • 又叫非聚簇索引,可以是普通索引、唯一索引、组合索引等。
  • 辅助索引的叶子节点存储的是主键值,需要通过主键值“回表”获取完整行数据。

3. 唯一索引(UNIQUE INDEX)

  • 保证索引列的值唯一。
  • 实现方式和辅助索引类似,只是加了唯一性约束。

4. 组合索引(联合索引)

  • 多个列组成一个索引,支持多条件查询。
  • 遵循最左前缀原则,只有从最左字段开始的连续条件才能用到索引。

5. 全文索引(FULLTEXT)

  • 用于对大文本字段(如文章内容)进行分词、全文检索。
  • InnoDB 从 MySQL 5.6 开始支持 FULLTEXT 索引。

6. 空间索引(SPATIAL INDEX)

  • 用于地理空间数据(GIS),如点、线、面等。

二、InnoDB 索引底层原理

1. B+树结构

  • InnoDB 所有索引(包括主键、辅助索引)都采用B+树结构。
  • B+树特点:有序、层次化,每个节点可以存储多个键值,便于范围查询。
  • 主键索引叶子节点存储整行数据,辅助索引叶子节点存储主键值

2. 聚簇索引与非聚簇索引

  • 聚簇索引:主键索引,叶子节点是整行数据。
  • 非聚簇索引:辅助索引,叶子节点是主键值,查完整数据需回表。

3. 回表查询

  • 通过辅助索引查找时,先定位到主键值,再通过主键索引查找整行数据,称为“回表”。

三、InnoDB 索引的特性

  1. 自动主键管理:没有主键时会自动创建隐藏主键。
  2. 支持多列联合索引:优化多条件查询。
  3. 支持前缀索引:对长字符串字段只索引前 N 个字符。
  4. 支持唯一约束:保证数据唯一性。
  5. 支持全文检索:适合文本搜索场景。
  6. 支持自适应哈希索引:InnoDB 会自动维护一份哈希索引(仅用于内存加速,用户不可见)。

四、索引使用场景与优化建议

1. 主键设计建议

  • 主键尽量使用自增整型,避免业务字段(如手机号、身份证号)做主键。
  • 主键字段应短小、稳定、不变更。

2. 索引字段选择建议

  • WHERE、ORDER BY、JOIN、GROUP BY 中频繁出现的字段建议加索引。
  • 高选择性(区分度高)的字段优先加索引。
  • 低选择性(如性别、状态)一般不加索引。

3. 联合索引优化

  • 多条件查询优先考虑联合索引。
  • 联合索引字段顺序遵循“最左前缀原则”和“高选择性字段在前”原则。

4. 覆盖索引

  • 查询字段都在索引中时,可避免回表,提高查询效率。

5. 避免冗余索引

  • 避免重复或无效索引,减少写入开销。

6. 索引失效场景

  • 在索引字段上使用函数或表达式(如 WHERE YEAR(create_time)=2023)会导致索引失效。
  • LIKE ‘%xxx’ 不能用索引,LIKE ‘xxx%’ 可以用索引。
  • 数据类型不一致(如字符串与数字比较)会导致索引失效。

五、实用命令与案例

1. 添加索引

ALTER TABLE user ADD INDEX idx_email(email);
ALTER TABLE orders ADD INDEX idx_user_status(user_id, status);

2. 查看索引

SHOW INDEX FROM user;

3. 删除索引

DROP INDEX idx_email ON user;

4. 使用 EXPLAIN 分析 SQL

EXPLAIN SELECT * FROM user WHERE email='abc@xx.com';

六、索引设计建议

  1. 主键选择

    • 优先选择自增整型(如 BIGINT UNSIGNED)为主键,短小且无业务含义。
    • 避免用业务字段(手机号、身份证号等)做主键。
  2. 高选择性字段优先建索引

    • 选择性 = 不同值数量 / 总行数,越高越适合建索引。
    • 例如用户ID、订单号等。
  3. WHERE、ORDER BY、JOIN、GROUP BY 常用字段要建索引

    • 优化常用查询路径,减少全表扫描。
  4. 优先考虑联合索引,而非多个单列索引

    • 多条件查询建议用联合索引。
    • 联合索引字段顺序遵循“最左前缀”原则和“高区分度字段在前”原则。
  5. 覆盖索引提升查询效率

    • 查询字段全部在索引中,无需回表。
    • 例如 SELECT id, name WHERE name=‘xxx’,有 (name, id) 索引。
  6. 合理使用前缀索引

    • 对长字符串字段(如 VARCHAR),只索引前 N 个字符(如 name(20)),减少索引体积。
  7. 唯一性约束用 UNIQUE 索引

    • 保证数据唯一性,如邮箱、用户名等。

七、避免索引失效

  1. 避免在索引字段上使用函数或表达式

    • 如 WHERE DATE(created_at) = ‘2023-01-01’,应改为 WHERE created_at BETWEEN ‘2023-01-01 00:00:00’ AND ‘2023-01-01 23:59:59’。
  2. LIKE 查询避免使用前置通配符

    • LIKE ‘%abc’ 无法用索引,LIKE ‘abc%’ 可以。
  3. 类型一致性

    • 查询条件类型应与字段类型一致,避免隐式转换导致索引失效。
  4. 避免对低选择性字段建索引

    • 如性别、状态等枚举值,通常不建索引。

八、索引维护建议

  1. 避免冗余和重复索引

    • 定期用 SHOW INDEX 检查索引,删除无用或重复索引。
  2. 控制索引数量

    • 每张表索引建议不超过5个,特殊业务场景除外。
  3. 变更表结构时同步调整索引

    • 新增/删除字段时同步规划索引。
  4. 定期用 EXPLAIN 分析慢 SQL

    • 检查索引是否命中,及时优化。

九、写入性能与索引平衡

  • 索引越多,写入/更新/删除性能越低。需权衡读写性能,业务写入频繁时,索引要更精简。
  • 批量写入时可临时移除部分索引,写完再重建。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐