索引是数据库表的“目录”,本质为B+Tree结构,支持范围查询、排序和分组;哈希索引仅适用于等值匹配且仅内存引擎支持;全文索引基于倒排索引,专用于文本搜索。

索引就是数据库表的“目录”,不是魔法,也不是开关,它是一套实际存在的、带排序结构的数据文件。没有它,WHERE 条件一查就得扫全表;有了它,MySQL 才能跳过无关数据,直接定位目标行。
索引本质是 B+Tree 结构,不是哈希表
InnoDB 默认用的是 B+Tree,不是哈希(HASH)索引。这意味着它天然支持范围查询(比如 age BETWEEN 18 AND 25)、ORDER BY 和 GROUP BY,而哈希索引只适合等值匹配(id = 10086),且不支持范围或排序。
-
B+Tree的叶子节点存完整索引键 + 主键值(聚簇索引下还存整行数据),非叶子节点只存键和指针,高度通常只有 3–4 层,百万级数据也只需 3–4 次磁盘 IO - 哈希索引在内存引擎(
MEMORY)里才有,InnoDB 不支持哈希索引;误以为加了索引就能“O(1) 查询”是常见误解 - 全文索引(
FULLTEXT)走的是倒排索引,和B+Tree完全不同,不能用于WHERE col LIKE '%abc%'这种模糊前缀查询
为什么能快几十上百倍?关键在减少磁盘 IO
慢不是因为 CPU 算得慢,而是因为磁盘读得太慢。索引提速的核心逻辑是:把随机读变成顺序读 + 少读。
- 无索引时:
SELECT * FROM user WHERE name = 'alice'可能要读取几百个数据页,逐行比对 - 有索引后:先读索引页(小、紧凑、有序),定位到对应主键,再按主键精准读 1–2 个数据页
- 如果查询只涉及索引列(比如
SELECT id, name FROM user WHERE name = 'alice'),甚至可能“覆盖索引”——连数据页都不用读,纯索引页搞定
哪些字段加索引才真正有效?
不是所有 WHERE 字段都值得建索引。有效性取决于选择性、查询频率和写入成本。
- 高选择性字段优先:比如
user_id、email(重复值少),别给gender或is_deleted建单列索引——区分度太低,优化器大概率弃用 - 组合索引注意最左前缀:
INDEX (a, b, c)能加速WHERE a=1、WHERE a=1 AND b=2、WHERE a=1 AND b=2 AND c=3,但对WHERE b=2或WHERE c=3无效 - 频繁更新的字段慎建索引:比如每秒更新多次的
last_login_at,索引维护开销会反噬查询收益 - 大字段(
TEXT、JSON)不能直接建普通索引,要用前缀索引(name(50))或函数索引(CAST(json_col->>'$.name' AS CHAR(32)))
容易被忽略的三个现实约束
索引不是越多越好,它的代价在生产环境里非常真实。
- 每个索引都占磁盘空间,InnoDB 中索引和数据一起存在
.ibd文件里;一张千万级用户表,5 个索引可能让文件体积翻倍 -
INSERT/UPDATE/DELETE时,MySQL 必须同步更新所有相关索引,写操作延迟会随索引数量线性上升 - 优化器可能“不用”你建的索引:比如统计信息过期、
WHERE条件用了函数(WHERE UPPER(name) = 'ALICE')、或者 MySQL 估算全表扫描反而更快(小表 or 高重复值)


















