带你慢慢理清MySQL索引那些事儿,细节和原理都有讲到
- 问答
- 2025-12-30 14:37:31
- 3
根据网络上多位技术博主,如“程序员小灰”、“JavaGuide”、“掘金社区”上的相关高赞文章,以及《高性能MySQL》书籍中的核心观点综合整理)
带你慢慢理清MySQL索引那些事儿,细节和原理都有讲到。
咱们先从一个最生活的例子开始,想象一下,你现在有一本非常厚的电话簿,里面记录了整个城市几百万人的姓名和电话号码,而且这些名字是完全没有按字母顺序排列的,是乱糟糟印上去的,让你在里面找到“张三”的电话,你该怎么办?你只能从第一页开始,一页一页地翻,一直翻到找到为止,这个过程,在MySQL里就叫“全表扫描”,效率非常低。
那怎么提高效率呢?很简单,我们给这本电话簿做一个“索引”,这个索引就像一本薄薄的小册子,里面按字母顺序列出了所有人的名字,并且在每个名字后面标明了这个人的详细信息在哪一页,你再找“张三”,就不用去翻那本厚书了,而是先拿起这本索引小册子,快速找到“张”开头的部分,然后很快找到“张三”,看到它对应的页码是第500页,你直接翻到厚书的第500页,就找到了张三的信息,这个“索引小册子”,就是MySQL里的“索引”。
在MySQL中,这个“索引小册子”的实现方式,最常用的是一种叫做“B+树”的结构,你可以把它想象成一棵倒过来的大树,有树根、树枝和树叶。

- 树根和树枝:相当于索引小册子的目录部分,树根告诉你,姓氏拼音A-L的在左边分支,M-Z的在右边分支,然后你走到M-Z这个树枝,它又告诉你,Ma-Mi在左,Mo-Mz在右……这样一层层地缩小范围。
- 树叶:相当于索引小册子里最终指向具体页码的那一行,在B+树里,这些“树叶”是顺序排列的,并且它们之间像链表一样连起来,这带来了两个巨大的好处:
- 查找非常快:从根节点开始,像翻书一样一层层往下找,很快就能定位到数据。
- 范围查找超级方便:比如你想找所有姓“张”的人,在乱序的书里你得全本翻,但在这里,你只需要在索引里找到第一个“张”,然后顺着树叶的链表顺序往下读就行了,因为所有“张”都挨在一起。
现在我们来聊聊索引的具体类型,最主要的就是两种:主键索引和普通索引。
- 主键索引(聚簇索引):这个比较特殊,它还记着两样东西:一是你建立索引的那个字段的值(比如你的用户ID),二是这条记录完整的其他所有数据,这就好比那本厚电话簿本身,就是按照用户ID的顺序来印刷的,通过主键查数据,速度是最快的,因为一次查找就能拿到全部数据,一张表只能有一个主键索引。
- 普通索引(二级索引/辅助索引):这个就更像我们举的例子里的那个“索引小册子”了,它只记两样东西:一是你建立索引的那个字段的值(比如你在“姓名”字段上建了索引,它就记着“张三”、“李四”),二是对应记录的主键值,你在“姓名”索引里找到“张三”,它后面标着主键ID是“101”,MySQL还得拿着这个“101”再去主键索引里查一遍,才能找到“张三”的完整信息,这个过程叫做“回表”。
理解了回表,你就能明白为什么有时候你明明建了索引,查询却还是不够快,比如你有一个查询是 SELECT * FROM users WHERE name = ‘张三’,而你在name字段上建了普通索引,那么MySQL会先在name索引里找到“张三”和其主键ID,然后再回表去主键索引里取回所有数据( 代表所有列),如果你的查询条件只是 SELECT id FROM users WHERE name = ‘张三’(id是主键),那么MySQL在name索引里就直接找到“张三”和id了,不需要回表,速度就会快很多,这种只需要在索引里就能拿到全部所需数据的情况,叫做“覆盖索引”,是优化查询的一个重要手段。
那是不是给每个字段都加上索引就好了呢?绝对不是!索引就像一把双刃剑。

好处很明显:大大提高了查询速度。
坏处也很明显:
- 占空间:你的“索引小册子”也是要占纸张的,数据库里就是要占磁盘空间的。
- 降低增删改的速度:你每增加一条记录,比如新来一个“赵六”,你不仅要在厚电话簿里加上他,还得在你的“索引小册子”里按字母顺序把他的名字插进去,如果你建了多个索引,就等于有好多本不同排序方式的小册子(比如按姓名一本,按电话号码一本),每次增删改都要同时更新所有这些小册子,当然就慢了。
建立索引要有策略,通常我们会给经常用来做查询条件的字段建索引,比如WHERE子句里的字段、JOIN连接用的字段,对于重复值特别多的字段,比如性别(只有男/女),建索引的意义就不大,因为索引一筛还是出来一半的数据,不如直接全表扫描了。
再讲一个常见的面试题:为什么MySQL要选择B+树来做索引,而不是用普通的二叉树或者哈希表?
- 相比二叉树:普通的二叉树在数据是顺序增加的时候(比如主键ID一直自增),会退化成一条直线,就像一根竹竿,查找效率又变成O(n)了,而B+树会通过分裂、合并等操作始终保持树的“矮胖”形态,这样查询的路径就很短,效率稳定,而且B+树的所有数据都在叶子节点,更适合磁盘I/O(一次可以读入一个节点的多个数据)。
- 相比哈希表:哈希表查询单个值非常快,是O(1),但是它有个致命缺点:不支持范围查询,你想找所有姓“张”的人,哈希表就无能为力了,因为它只能计算“张三”、“张四”每个值的哈希值去定位,而这些值在哈希表里是散列存放的,根本不挨着,而B+树的叶子节点是顺序链表,做范围查询简直是天生优势。
希望这些生活中的比喻和一步步的拆解,能帮你慢慢理清MySQL索引的那些核心事儿,索引是个强大的工具,但要用对地方。
本文由革姣丽于2025-12-30发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/71320.html
