嗨呀大家好,我是小米,一个31岁还保持着程序员浪漫的大哥哥(别笑,技术圈我们永远年轻~)。
今天又是被一位朋友的社招面试经历触发的一天。
故事要从昨天中午的火锅说起。
一顿火锅,一场社招的"索引拷问"
"我感觉我被那个面试官当成了索引百科全书了!"小孟夹着一块牛肚,一脸生无可恋。
我笑了笑:"问什么了?"
"就问我MySQL索引的类型!我一开始挺开心的,这题我熟!我说了B+树索引、哈希索引,结果对方继续追问'联合索引呢?前缀索引呢?空间索引呢?全文索引呢?主键索引、唯一索引和普通索引又怎么区分?'我当场卡壳。"
啧啧,这可不是你一个人卡。
MySQL面试题里,"索引的类型"这题最常见,也最容易让人掉进"答了,却答不全"的坑。
所以今天,小米我就来一次火锅级的梳理 ------把所有你在MySQL面试里能遇到的"索引类型"讲清楚。
记住:这一题不止是"几种索引"的死记硬背,更是对原理理解、场景适配和性能意识的综合考察。
逻辑分类:主键索引、唯一索引、普通索引、全文索引、空间索引
我们先来个最常见分类法,基于功能逻辑划分的5种类型。
1. 主键索引(Primary Key Index)
- 每张表只能有一个主键索引,字段值必须唯一且非空。底层用B+树实现。
- 面试加分说法:在InnoDB中,主键索引就是聚簇索引(Clustered Index) ,数据和索引存储在一起,按照主键顺序排列。
2. 唯一索引(Unique Index)
- 保证列值唯一,但可以为NULL;一个表可以有多个唯一索引。
- 面试常见追问:多个NULL算不算违反唯一?不算,因为MySQL认为NULL ≠ NULL。
3. 普通索引(Index)
- 最基本的索引类型,没有任何限制,用得最多,性能最自由。
- 场景:频繁作为 WHERE 查询条件的字段,但无需唯一限制。
4. 全文索引(Fulltext Index)
- 用于大文本字段(如 TEXT、VARCHAR),进行"全文检索"。
- 支持自然语言搜索,适合做文章、搜索引擎之类。
5. 空间索引(Spatial Index)
- 基于 R-Tree 实现的索引,支持空间数据类型(如 GEOMETRY)。主要用于GIS系统(地理信息系统),普通业务中不常见。
物理结构分类:B+树索引 vs 哈希索引 vs R树索引 vs 全文倒排索引
逻辑类型讲完了,我们再来看物理结构维度的分类方式,这个在深入原理时特别重要。
1. B+树索引(B+ Tree Index)
InnoDB默认索引类型。
- 支持范围查找
- 查询性能随层级增加而略有降低
- 聚簇索引(主键)和二级索引(辅助索引)都是B+树
记住:聚簇索引和B+树不是等价关系,聚簇是一种数据组织方式,B+树是结构。
2. 哈希索引(Hash Index)
Memory引擎中支持。
- 基于哈希表,只适用于等值查询
- 不支持范围查找、排序、最左匹配
- 非常快,但限制也多
面试常问陷阱:为啥InnoDB不用哈希索引?因为它不支持范围查找、顺序遍历,而InnoDB需要这些能力。
3. R树索引(R-Tree Index)
- 专为空间数据设计,比如存储经纬度、几何对象等。
- 只适用于MyISAM或空间引擎,InnoDB直到MySQL 8.0才初步支持。
4. 倒排索引(Inverted Index)
全文索引背后的结构。
- 每个关键字对应文档集合
- 快速实现模糊搜索,分词支持强
- 但对更新不敏感,性能不如B+树
创建方式维度:单列索引、联合索引、前缀索引、函数索引、虚拟列索引
是的,MySQL索引还有一大类是从创建方式来分类。
1. 单列索引
- 为单个字段创建索引,是最基本形式。
- 例如:CREATE INDEX idx_name ON user(name);
2. 联合索引(复合索引)
- 包含多个字段的索引。
- 例如:CREATE INDEX idx_name_age ON user(name, age);
- 最左前缀法则:MySQL只使用从最左边起连续的字段,比如只用到了name和age,但跳过name是不会使用索引的。
3. 前缀索引
- 对字符串字段,截取前几个字符建立索引。
- 适用于很长的字符串,节省存储空间。
- 例如:CREATE INDEX idx_name_prefix ON user(name(10));
- 面试进阶点:前缀索引不能用于ORDER BY和GROUP BY等排序操作。
4. 函数索引(Function-based Index)
- MySQL 8.0支持,可以对表达式或函数结果建立索引。
- 例如:CREATE INDEX idx_lower_name ON user((LOWER(name)));
- 注意小括号是必须的。
5. 虚拟列索引(Generated Column Index)
通过生成列建立索引,让表达式结果变成字段。
更灵活,也更适合索引表达式。
如何面试回答这个问题,才能不"只说个B+树"
现在回到文章的开头,小孟被问的那道题:
"MySQL索引有哪些类型?"
你要这么回答:
答题模板:
MySQL索引从不同维度可以分为多种类型。
按照功能逻辑来分,有主键索引、唯一索引、普通索引、全文索引、空间索引;
按照底层结构,常见的有B+树索引(用于InnoDB)、哈希索引(用于Memory)、R-Tree索引(空间索引)、倒排索引(全文索引);
从创建方式来看,还有单列索引、联合索引、前缀索引、函数索引和虚拟列索引等。
实际开发中,我们会根据查询场景、字段类型和查询频率综合设计索引结构。
这不仅考察你对索引的分类是否熟悉,更重要的是------是否知道怎么选择使用它们。
实战思考:这几个坑你踩过没?
- 字符串字段不加前缀索引导致索引失效
- 联合索引顺序写反,结果走不了索引
- 全文索引没用MATCH AGAINST而是用LIKE,性能飘了
- 表中数据少,加索引反而慢(别忘了MySQL的成本优化器会判断是否使用索引)
一个问题,背后是整个索引体系的掌握
好了,今天的小米课堂就到这里啦。
你看,MySQL面试时常常一句话"索引有哪几种类型",其实背后包含的是:
- 索引逻辑结构
- 底层实现原理
- 查询适配场景
- 性能优化意识
学会不是难,难的是理清这些概念之间的边界和联系。
火锅吃完了,故事讲完了。
希望下一次你面对"这题我熟!"的时候,是真的熟,熟得连面试官都忍不住说一句:
"你对索引理解得很透,继续聊聊执行计划吧~"
END
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号"软件求生",获取更多技术干货!