首页技术栈归档照片墙音乐日记随想收藏夹友链留言关于

MySQL 索引优化实战

写作时间:2026-07-08

MySQL 索引优化实战

B+Tree 索引原理

MySQL InnoDB 引擎默认使用 B+Tree 索引结构:

  • 所有数据存放在叶子节点
  • 非叶子节点只存键值,不存数据
  • 叶子节点通过双向链表连接,支持高效范围查询
  • 树的高度通常 2-3 层,每次查询只需 2-3 次磁盘 I/O

索引类型及创建

-- 主键索引(聚簇索引,自动创建) ALTER TABLE article ADD PRIMARY KEY (id);

-- 唯一索引 CREATE UNIQUE INDEX idx_slug ON article (slug);

-- 普通索引 CREATE INDEX idx_title ON article (title);

-- 联合索引(重要!) CREATE INDEX idx_cat_time ON article (category_id, publish_time);

最左前缀原则

联合索引 (a, b, c) 相当于创建了三个索引:

  • (a) 可用
  • (a, b) 可用
  • (a, b, c) 可用
  • (b, c) 不可用 — 跳过了 a

CREATE INDEX idx_abc ON test (a, b, c);

-- 走索引 SELECT * FROM test WHERE a = 1; SELECT * FROM test WHERE a = 1 AND b = 2;

-- 不走索引 SELECT * FROM test WHERE b = 2; SELECT * FROM test WHERE c = 3 ORDER BY b;

EXPLAIN 执行计划

EXPLAIN SELECT * FROM article WHERE category_id = 5 ORDER BY publish_time DESC;

关键字段解读:

字段 含义 理想值
type 访问类型 const > ref > range > index > ALL
key 使用的索引 非 NULL
rows 预估扫描行数 越小越好
Extra 额外信息 Using index(覆盖索引最好)

需要警惕的 Extra 值:

  • Using filesort — 需要额外排序,考虑加索引
  • Using temporary — 使用了临时表
  • Using where — 有过滤条件但没用到索引

常见索引优化场景

  1. WHERE 条件列加索引
  2. ORDER BY 列加索引(避免 filesort)
  3. JOIN 关联列加索引
  4. 高选择性的列优先(性别不适合单独索引)
  5. 覆盖索引:查询列全部在索引中,无需回表

-- 覆盖索引示例 CREATE INDEX idx_cover ON article (category_id, publish_time, title); SELECT category_id, publish_time, title FROM article WHERE category_id = 5; -- Using index — 直接从索引返回,无需回表

慢查询排查

-- 开启慢查询日志 SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1;

优化步骤:

  1. 查看慢查询日志,定位慢 SQL
  2. EXPLAIN 分析执行计划
  3. 添加合适的索引
  4. 优化 SQL 写法(避免 SELECT *、优化 JOIN 顺序、用 EXISTS 替代 IN)
  5. 考虑读写分离、分库分表
avatar

yuanyourdomain

写代码,做研究,记录生活。

RECOMMENDED

MyBatis 动态 SQL

2026-07-08

Nginx 基础入门

2026-07-08

Maven 多模块与私服

2026-07-08