
一、什么是MySQL索引
MySQL索引是一种用于快速查询和检索数据的数据结构,其本质类似于书本的目录。在没有目录的情况下,要在书中查找特定内容需要逐页翻阅(相当于数据库的全表扫描);而有了目录后,可以先通过目录定位到页码,再直接翻到该页,从而极大地提高了查找速度。
在MySQL中,索引是在存储引擎层实现的,因此不同存储引擎的索引底层实现可能会有所不同。最常见的索引底层数据结构是B+树。
二、索引的底层数据结构
为什么MySQL索引采用B+树而不是B树、二叉树或Hash?主要原因如下:
B+树 vs B树:B+树的非叶子节点只存储键值,不存储数据,这使得单个节点可以容纳更多的键值,从而降低树的高度,减少磁盘I/O次数。同时,B+树的所有叶子节点通过指针相连,非常适合范围查询。
B+树 vs Hash:Hash索引虽然等值查询极快,但不支持范围查询、排序和最左前缀匹配。
B+树 vs 二叉树:二叉树层级过深,会导致大量的磁盘I/O,性能极差。
三、索引的分类
根据不同的维度,MySQL索引可以分为以下几类:
1. 按数据结构分
聚簇索引:将数据行和主键索引存储在同一棵B+树中。叶子节点存放了整行数据的完整记录。一张表只能有一个聚簇索引,通常就是主键。
非聚簇索引:也叫二级索引或辅助索引。叶子节点存放的是主键的值。通过非聚簇索引查找数据时,通常需要先查到主键值,再回表到聚簇索引中查询整行数据,这个过程称为回表。
2. 按逻辑功能分
主键索引:特殊的唯一索引,不允许为空,每张表只能有一个。
唯一索引:索引列的值必须唯一,但允许有空值。
普通索引:最基本的索引,没有任何限制。
全文索引:用于查找文本中的关键词,目前只有InnoDB和MyISAM存储引擎支持。
四、索引的基本操作
以下为索引的创建、查看与删除的常用SQL语句:
-- 创建普通索引 CREATE INDEX idx_name ON table_name(col_name); -- 创建唯一索引 CREATE UNIQUE INDEX idx_email ON table_name(email); -- 创建复合索引(联合索引) CREATE INDEX idx_age_gender ON table_name(age, gender); -- 查看表中的索引 SHOW INDEX FROM table_name; -- 删除索引 DROP INDEX idx_name ON table_name; -- 强制使用某个索引查询(适用于优化器选错索引的场景) SELECT * FROM table_name FORCE INDEX(idx_name) WHERE col_name = 'value';
五、索引的优化与最佳实践
合理使用索引能大幅提升性能,但滥用索引也会导致写入变慢和存储空间浪费。以下是核心的优化原则:
1. 最左前缀法则
在复合索引中,查询必须从索引的最左列开始并且不能跳过中间的列。如果建立了索引 idx_a_b_c (a, b, c),则查询条件为 a,a, b,a, b, c 都能命中索引;如果查询条件仅为 b 或 c,则无法命中该复合索引。
2. 避免索引失效的常见场景
对索引列使用函数或计算:如
WHERE YEAR(create_time) = 2023会导致索引失效,应改写为WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01'。隐式类型转换:如字段
phone为字符串类型,查询WHERE phone = 13800138000会导致索引失效,应加上引号。使用不等于:
!=或<>通常会导致索引失效,优化器可能认为全表扫描更快。LIKE以通配符开头:
LIKE '%abc'会导致索引失效,而LIKE 'abc%'可以命中索引。使用 OR 连接非索引列:如果 OR 前后的列中有一个没有索引,那么整个查询将放弃使用索引。
3. 覆盖索引
如果一个索引包含了查询所需的所有字段(即 SELECT、WHERE、ORDER BY 等涉及的列都在复合索引中),数据库就可以直接通过索引返回数据,而无需回表查询聚簇索引,这被称为覆盖索引。使用覆盖索引可以极大地提升查询性能,特别是在分页查询场景中。
你可以通过在线工具如 www.ipipp.com 提供的SQL性能分析工具来验证执行计划中的 Extra 字段是否出现了 Using index,以此判断是否成功使用了覆盖索引。
4. 索引下推
索引下推是MySQL 5.6引入的优化机制。在没有索引下推时,存储引擎根据复合索引查找到满足最左前缀的记录后,会全部返回给Server层,由Server层判断其他条件是否满足;有了索引下推后,存储引擎在查找时,会先判断复合索引中包含的其他条件是否满足,仅将满足全部索引条件的记录返回给Server层,从而减少了回表次数和层间交互的数据量。
六、总结
索引是MySQL性能优化的核心手段。理解B+树的结构、聚簇索引与非聚簇索引的区别,以及最左前缀法则和索引失效场景,是写出高性能SQL的基础。在实际开发中,务必结合业务查询模式,优先考虑建立复合索引和覆盖索引,并定期使用 EXPLAIN 分析慢查询执行计划,让数据库始终保持高效运转。