(索引 + SQL 优化):《MySQL 底层探秘②:B + 树索引与 Explain 实战,根治线上慢 SQL》

MySQL深度解析(第二篇)索引原理、SQL优化、执行计划与慢查询

标签:MySQL索引,B+树,explain,SQL优化,慢查询

前言

第一篇搞定了InnoDB底层、事务、MVCC。开发工作中最常打交道就是索引,大部分线上性能问题,根源都是索引设计不合理、写出低效SQL。本篇重点讲解InnoDB聚簇索引原理、索引分类、索引失效场景、Explain执行计划,慢查询排查,以及SQL优化实战技巧。

一、InnoDB聚簇索引(主键索引)

InnoDB使用聚簇索引:表数据本身按照主键有序存放在B+树叶子节点,索引和数据在一起。

  • 叶子节点:完整的一行数据,并且按主键排序
  • 非叶子节点:只存放主键值+页指针,用于索引检索

对比MyISAM非聚簇:索引和数据文件分开,索引叶子节点存储数据行地址。

聚簇索引 vs 二级索引

索引类型 叶子节点存储内容 查询流程 特点
聚簇索引(主键索引) 完整行数据 主键查询直接拿到行数据 主键必须有序;主键不宜过大,二级索引会变大
二级索引(普通索引) 主键值 查到主键,再回表去主键索引读取完整数据(回表) 联合索引最左前缀原则,减少回表可以使用覆盖索引

覆盖索引:二级索引包含查询所需要全部字段,不需要回表,性能极高。

二、B+树索引特点

InnoDB索引底层是B+树,不是二叉树、B树。

  1. 所有数据都在叶子节点,非叶子只存索引键,树矮,IO次数少
  2. 叶子节点之间用双向链表串联,范围查询(> < between,order by)非常高效
  3. 节点大小等于InnoDB页(默认16KB),一页可以存大量索引条目,树高度一般2~4层

三、索引分类

  1. 主键索引PRIMARY:聚簇索引,唯一非空,一张表只能一个
  2. 唯一索引UNIQUE:索引列不能重复,可以为NULL
  3. 普通索引INDEX:普通二级索引,允许重复和NULL
  4. 联合索引(复合索引) :多个字段组合索引,遵循最左前缀原则
  5. 全文索引FULLTEXT:长文本分词检索,不适合模糊like '%xxx%'

索引设计黄金原则

  1. 联合索引,把区分度高、查询频率高的字段放前面
  2. 尽量使用覆盖索引,避免回表
  3. 索引字段尽量小,不要在大字符串、大文本建索引
  4. 不要在低区分度字段(性别、状态)单独建索引
  5. 索引不是越多越好,索引会降低写入性能(增删改需要维护B+树)

四、索引失效常见场景

  1. 索引列做函数运算、隐式类型转换
  2. like 以%开头 like '%abc',无法走B+树索引
  3. or两边字段,有一个没有索引
  4. 违反最左前缀原则,跳过前面索引列
  5. MySQL优化器判断全表扫描比索引更快,主动放弃索引

五、Explain执行计划详解

使用 explain select xxx; 查看SQL执行计划,判断是否命中索引。

字段 含义 关注点
id 查询序号,子查询、关联查询标识 id越大优先级越高
select_type 查询类型,SIMPLE简单查询、SUBQUERY子查询、DERIVED派生表 尽量避免DEPENDENT SUBQUERY相关子查询
table 当前访问哪张表
type 访问类型,性能从优到劣:system>const>eq_ref>ref>range>index>ALL 目标至少range/ref,ALL代表全表扫描,需要优化
possible_keys 理论可用索引 仅参考,不一定实际使用
key 实际选用索引 NULL代表没用到索引
key_len 索引使用字节长度 判断联合索引使用多少列
ref 索引匹配条件,哪些列/常量和索引对比
rows 预估扫描行数 越小越好,评估扫描代价
Extra 额外信息,核心重点 Using filesort 文件排序;Using temporary临时表;Using index覆盖索引;Using where

重点警告:Using filesort(文件排序)、Using temporary(临时表)属于高危性能信号,代表MySQL无法利用索引排序,需要额外内存/磁盘排序,大数据集性能很差。

六、慢查询日志

慢查询日志用来捕获执行超过阈值的SQL,是线上排查性能问题的利器。

核心参数:

  • slow_query_log:开启/关闭慢日志
  • long_query_time:慢查询阈值(单位秒,默认10s)
  • log_queries_not_using_indexes:记录没有使用索引的SQL

生产建议:long_query_time 设置为1s,开启记录未走索引SQL,定期分析慢日志。

七、SQL优化通用思路

  1. 先用explain查看执行计划,定位是否全表扫描、文件排序、临时表
  2. 优先建立合适索引,利用覆盖索引减少回表
  3. 避免select *,只查询业务需要字段,减少数据传输,更容易触发覆盖索引
  4. 减少子查询,优先使用JOIN;JOIN字段保证类型一致,建立索引
  5. 分页优化:大offset分页,不要limit 100000,10,推荐主键id过滤 where id>xxx limit 10
  6. 减少大事务,大事务持有锁时间长,容易锁等待

第二篇小结

本篇掌握B+树索引、聚簇索引、联合索引最左前缀、索引失效场景,看懂explain执行计划,慢查询定位方法和SQL优化方案。

索引优化是开发高频工作,但索引只能解决查询性能。第三篇我们学习主从复制、MGR、高可用架构,锁详解,运维参数调优,线上故障排查和最佳实践。

相关推荐
箓维1 小时前
网络基础(2)IP和MAC的区别与报文封装
linux·网络
wtblszn1 小时前
活性炭吸附塔组态监控运维系统方案
运维
lisanmengmeng1 小时前
pushgateway
linux·运维·服务器·网络
我滴老baby1 小时前
自建服务20个,书签300条?我用一个Docker容器做了个“服务启动台”,手机也能打开
运维·docker·容器
Marst Code1 小时前
(Unix)一切皆文件
服务器·unix
Rabitebla1 小时前
【Linux底层原理】 工具篇(二):Vim 编辑器基础操作与简单配置
linux·c++·编辑器·vim
lwx9148521 小时前
Docker容器模拟主机
运维·docker·容器
李纲明1 小时前
WordPress 媒体库上传图片报「HTTP 错误」:php.ini、临时目录、安全插件和 CDN 怎么逐层查
运维·php·上传·cdn·wordpress·媒体库
Marst Code1 小时前
(Unix) fork-exec 进程创建与程序加载解耦
服务器·unix