(索引 + 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、高可用架构,锁详解,运维参数调优,线上故障排查和最佳实践。

相关推荐
微订校园外卖系统8 分钟前
校园代取快递系统选型:现成系统与定制开发的技术核对项
大数据·运维·人工智能·外卖系统·本地生活·微订
QXWZ_IA13 分钟前
管道GIS测绘如何实现自动化成图:三种成图方式怎么选
运维·人工智能·安全·自动化
一条破秋裤17 分钟前
【1112】Linux中断【整理】
linux·运维·服务器
分布式存储与RustFS25 分钟前
OpenObserve 的日志别堆本地盘:用 RustFS 当它的对象存储底座
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
CodeYp20192 小时前
第14讲:传输层协议 UDP
linux·udp
北京迅为2 小时前
案例分享 | RK182X算力卡:多路视频VLM监控,四路画面AI同时看懂,一句人话说清现场
linux·人工智能·嵌入式·rk3588·算力卡·rk182x
新*2 小时前
ES 7.17 三节点 Docker 集群接入 IK 自定义词典:一次从丢插件到热更新的完整排障
运维·elasticsearch·docker·中文分词·ik分词
虹科数字化与AR2 小时前
农业机械AR质检ROI怎么算?从搬运、测量、返工和交付成本入手
经验分享·ar·质检·农业机械
风翼靓崽2 小时前
jenkins搭建与简单使用
运维·jenkins
lzx_00214 小时前
Linux 进程(三) 从进程状态到僵尸进程、孤儿进程
linux·服务器