MySQL索引是数据库存储引擎用于快速定位数据行的特殊数据结构,类似于书籍的目录,能够避免全表扫描,大幅减少查询需要扫描的数据量,是优化数据库查询性能的核心手段。合理的索引设计可以让查询耗时从秒级降低到毫秒级,而不合理的索引反而会增加数据写入和更新的开销。

MySQL索引的核心类型
MySQL支持多种索引类型,不同类型的索引适用场景差异较大,开发者需要根据实际业务需求选择:
- 普通索引:最基本的索引类型,没有任何约束,仅用于加速查询,允许索引列包含重复值和空值。
- 唯一索引:索引列的值必须唯一,允许为空,常用于需要保证列值唯一性的场景,比如用户手机号、邮箱字段。
- 主键索引:特殊的唯一索引,不允许有空值,每个表只能有一个主键索引,InnoDB引擎中主键索引同时也是聚簇索引。
- 全文索引:用于文本内容的模糊查询优化,支持对
CHAR、VARCHAR、TEXT类型字段创建,适合文章内容、评论等场景的搜索。 - 组合索引:由多个列共同组成的索引,遵循最左前缀匹配原则,合理设计组合索引可以覆盖多个查询场景。
常见索引的底层数据结构
MySQL中最常用的索引是基于B+树实现的,尤其是InnoDB存储引擎的默认索引结构就是B+树索引,其结构特点如下:
- B+树的非叶子节点仅存储索引键和子节点指针,不存储实际数据,因此单个节点可以存储更多的索引键,树的高度更低,查询时磁盘IO次数更少。
- 所有实际数据都存储在叶子节点中,叶子节点之间通过双向链表连接,非常适合范围查询和排序操作。
- 聚簇索引的叶子节点存储的是整行数据,而非聚簇索引的叶子节点存储的是主键值,查询时需要回表到聚簇索引获取完整数据。
除了B+树索引,Memory存储引擎还支持哈希索引,哈希索引基于哈希表实现,等值查询效率极高,但不支持范围查询和排序,使用场景相对有限。
索引的实用使用技巧
合理设计组合索引
组合索引的设计要遵循最左前缀原则,把查询中过滤性最强的列放在最左边,同时尽量让索引覆盖常用查询的所有字段,避免回表。比如经常执行查询SELECT id, name FROM user WHERE age = 20 AND city = '北京',可以创建组合索引(age, city, name, id),其中id是主键,InnoDB会自动将主键包含在所有非聚簇索引中,实际创建时可以省略id。
使用覆盖索引减少回表
覆盖索引指的是查询的所有字段都包含在索引中,不需要回表查询聚簇索引获取完整数据,能够大幅提升查询效率。比如下面的查询就可以使用覆盖索引:
-- 表user有索引 (name, age) SELECT name, age FROM user WHERE name LIKE '张%';
控制索引数量
虽然索引能提升查询效率,但每个索引都会占用额外的存储空间,同时会在数据插入、更新、删除时增加索引维护的开销。一般来说,单个表的索引数量不建议超过5个,对于更新频繁的字段要谨慎创建索引。
常见索引失效场景
即使创建了索引,部分查询场景下索引也可能无法生效,常见的失效场景包括:
- 对索引列进行函数操作或者表达式计算,比如
SELECT * FROM user WHERE YEAR(create_time) = 2024,索引会失效。 - 使用
LIKE以通配符开头,比如LIKE '%张三',无法使用索引,而LIKE '张三%'可以使用索引。 - 查询条件中使用
OR,且OR两边的列不是都有索引,整个查询的索引会失效。 - 索引列参与类型转换,比如索引列是字符串类型,查询时传入数字,会导致索引失效。
- 组合索引没有遵循最左前缀原则,比如组合索引是
(a, b, c),查询条件只有b和c,无法使用索引。
索引创建与查看的基础操作
以下是MySQL中索引相关的常用操作示例:
-- 创建普通索引 CREATE INDEX idx_age ON user(age); -- 创建唯一索引 CREATE UNIQUE INDEX idx_phone ON user(phone); -- 创建组合索引 CREATE INDEX idx_age_city ON user(age, city); -- 查看表的索引信息 SHOW INDEX FROM user; -- 删除索引 DROP INDEX idx_age ON user;
在实际开发中,还需要结合EXPLAIN命令分析查询语句的执行计划,判断索引是否被正确使用,逐步优化索引设计。