数据库索引(Index)是一种数据结构,用于加速按列(或列组合)的查找与排序。MySQL InnoDB、PostgreSQL 等常用 B+ 树实现索引。索引可显著提升 SELECT 速度,但会增加写入(INSERT/UPDATE/DELETE)成本和存储占用;设计时需结合查询模式与写入比例。本文介绍 B+ 树索引原理、复合索引与最左前缀、覆盖索引以及 EXPLAIN 分析与实践建议。
一、索引为何重要:数据与影响
无索引时,数据库往往进行全表扫描(Full Table Scan),数据量大时延迟急剧上升。合理索引可将常见查询从秒级降到毫秒级。但索引并非越多越好:过多索引会拖慢写入并占用空间。
| 场景 | 无索引 | 有合适索引 | 说明 |
|---|---|---|---|
| 等值查询(主键/唯一) | 全表扫描 | O(log N) 查找 | B+ 树高度低 |
| 范围查询、ORDER BY | 全表扫描+排序 | 索引范围扫描 | 叶子有序 |
| 写入 | 仅写数据 | 同时更新索引 | 索引越多写入越慢 |
数据来源:MySQL/PostgreSQL 官方文档与性能调优指南(综合整理)。
二、B+ 树索引原理
B+ 树是一种多路平衡查找树:非叶子节点存键(用于路由),叶子节点存数据或主键,且叶子通过指针串联,便于范围查询与排序。InnoDB 中:主键索引(聚簇索引)的叶子存完整行数据;二级索引的叶子存主键值,通过主键再查一次称为「回表」。
2.1 聚簇与二级索引
聚簇索引:表数据按主键顺序存储,因此按主键范围查询效率高。二级索引:按索引列排序,叶子存主键;若 SELECT 的列不都在二级索引中,需回表取完整行。
三、复合索引与最左前缀
复合索引(联合索引)由多列组成,如 (a, b, c)。最左前缀原则:查询条件必须从最左列开始连续使用,才能利用该索引。例如 (a,b,c) 可用于 WHERE a=?、WHERE a=? AND b=?、WHERE a=? AND b=? AND c=?,不能用于仅 WHERE b=? 或 WHERE c=?。
3.1 列顺序建议
等值条件、高选择性(区分度大)的列放前面;范围条件(>、<、BETWEEN)的列放后面,因为范围列之后的索引列无法用于排序与过滤。
| 索引 | 可用查询条件 | 不可用 |
|---|---|---|
| (a,b,c) | a; a AND b; a AND b AND c | b; c; b AND c |
| 覆盖索引 | SELECT 的列全部在索引中 | 无需回表,性能最佳 |
四、覆盖索引
若二级索引已包含查询所需的全部列,则无需回表,称为覆盖索引(Covering Index)。可显著减少随机 I/O,尤其对列表查询有利。设计时可将高频 SELECT 的列加入复合索引(在满足最左前缀与顺序前提下)。
五、EXPLAIN 与优化
使用 EXPLAIN(或 EXPLAIN ANALYZE)查看执行计划。关注:type(ALL 为全表扫描,应尽量避免;ref、range、index 等为使用索引)、possible_keys、key、rows(估算行数)。若 type 为 ALL 且 rows 很大,应检查 WHERE、ORDER BY 是否可加索引或改写查询。
六、索引设计要素权重
基于实际数据库优化经验,以下要素的影响程度(相对权重,满分 100):
说明:权重基于 MySQL/PostgreSQL 优化项目实践归纳,仅供参考。
七、小结
索引设计需结合查询模式,遵循最左前缀与覆盖索引原则,并权衡读写与空间。定期用 EXPLAIN 分析慢查询,逐步优化。若数据库部署在 VPC 内网,可参考《MySQL VPC 内网架构》;若需 API 与安全设计,可阅读《API 安全设计最佳实践》。