当我碰到一条慢SQL,我会这样做...
SQL性能优化利器:EXPLAIN详解 EXPLAIN是MySQL的性能分析工具,可显示查询执行计划。关键分析点包括:查询类型(select_type)、连接类型(type,应避免ALL全表扫描)、索引使用情况(possible_keys/key)和预估扫描行数(rows)。优化重点在于确保使用合适的索引(至少range级别),减少扫描行数,避免临时表和文件排序(Using temporary/f
EXPLAIN用法详解
什么是EXPLAIN?
EXPLAIN是SQL性能分析工具,显示MySQL如何执行查询语句。
基本用法
EXPLAIN SELECT * FROM 表名 WHERE 条件;
EXPLAIN结果列解析
1. id - 查询标识
-
相同id:执行顺序从上到下
-
不同id:id值越大优先级越高
-
NULL:表示联合结果
2. select_type - 查询类型
-
SIMPLE:简单SELECT查询 -
PRIMARY:最外层查询 -
SUBQUERY:子查询 -
DERIVED:派生表(FROM子句中的子查询) -
UNION:UNION中的第二个或后续查询
3. table - 访问的表
-
显示正在访问的表名
-
<derivedN>:派生表 -
<unionM,N>:UNION结果
4. partitions - 分区信息
-
查询匹配的分区
-
非分区表为NULL
5. type - 连接类型(重要指标)
从优到劣排序:
-
system:表只有一行 -
const:通过主键或唯一索引一次找到 -
eq_ref:唯一索引扫描,对于每个索引键只有一条匹配 -
ref:非唯一索引扫描,返回匹配某个值的所有行 -
range:索引范围扫描 -
index:全索引扫描 -
ALL:全表扫描(需要优化)
6. possible_keys - 可能使用的索引
-
查询可能使用的索引列表
-
NULL表示没有相关索引
7. key - 实际使用的索引
-
查询实际使用的索引
-
NULL表示未使用索引
8. key_len - 索引长度
-
使用的索引字节数
-
可判断是否使用了索引的全部列
9. ref - 索引引用
-
显示索引的哪一列被使用
-
const:常量值
-
列名:使用的列
10. rows - 预估扫描行数
-
执行查询需要检查的大致行数
-
值越小越好
11. filtered - 过滤比例
-
表示存储引擎返回的数据在server层过滤后,剩余数据的百分比
-
100%表示无需额外过滤
12. Extra - 额外信息(重要)
常见值及含义:
-
Using index:使用覆盖索引 -
Using where:在存储引擎检索后过滤 -
Using temporary:使用临时表(需要优化) -
Using filesort:使用文件排序(需要优化) -
Using join buffer:使用连接缓存 -
Impossible WHERE:WHERE条件永远为false
使用EXPLAIN分析性能的步骤
-
检查type列:确保不是ALL,至少是range级别
-
检查key列:确认使用了合适的索引
-
检查rows列:预估扫描行数是否合理
-
检查Extra列:避免出现Using temporary和Using filesort
-
分析执行顺序:通过id确定查询执行计划
性能优化建议
需要优化的信号:
-
type为ALL(全表扫描)
-
rows值很大
-
Extra中出现Using filesort或Using temporary
-
key为NULL(未使用索引)
优化措施:
-
为查询条件添加合适的索引
-
优化SQL语句结构
-
考虑使用覆盖索引
-
调整查询条件顺序以利用复合索引
通过EXPLAIN分析,可以系统性地定位查询性能瓶颈,并采取针对性的优化措施。
索引原理与优化
索引为什么能提升查询速度?
核心原理:索引就像书籍的目录
没有索引的情况(全表扫描):
数据库需要逐行检查:第1行 → 第2行 → 第3行 → ... → 找到目标数据
时间复杂度:O(n)
有索引的情况(快速定位):
通过索引树结构:根节点 → 分支节点 → 叶子节点 → 直接定位数据
时间复杂度:O(log n)
索引的工作机制
B+树索引结构:
-
根节点:存储索引键的范围指针
-
中间节点:进一步细分范围
-
叶子节点:存储实际数据位置指针
-
所有数据都在叶子层,形成有序链表
索引查找过程:
-
从根节点开始比较
-
根据比较结果选择分支
-
逐层向下直到叶子节点
-
通过指针直接访问数据
索引的最佳实践
应该创建索引的字段:
-
主键和外键字段
-
WHERE条件中频繁使用的字段
-
JOIN连接条件的字段
-
排序和分组字段
-
高基数字段(唯一值多的字段)
不建议创建索引的情况:
-
数据量很小的表
-
更新频繁的字段
-
低基数字段(如性别、状态标志)
-
很少在查询中使用的字段
复合索引策略
-
遵循"最左前缀"原则
-
将高选择性字段放在前面
-
考虑查询的排序和分组需求
更多推荐


所有评论(0)