2021-01-19 00:34:48
分析MySQL查询的执行计划主要通过EXPLAIN命令实现,其核心步骤包括生成执行计划、解读关键字段信息,并基于结果优化查询性能。 以下是具体分析方法与优化策略:
一、使用EXPLAIN命令生成执行计划EXPLAIN是MySQL提供的分析工具,通过模拟查询执行过程生成执行计划,展示查询的访问路径、索引使用情况及预估行数等关键信息。
EXPLAIN EXTENDED(MySQL 5.6及之前版本):提供更详细的执行计划信息(MySQL 8.0+已移除,改用EXPLAIN FORMAT=JSON)。
EXPLAIN FORMAT=JSON:以JSON格式输出执行计划,包含更丰富的细节(如成本估算、优化器决策路径)。
执行计划结果集包含以下核心字段,其含义及优化方向如下:
id查询的序列标识符,数值越大优先级越高。同一查询中可能存在多个id(如子查询),需结合select_type分析执行顺序。
select_type查询类型,常见值包括:
SIMPLE:简单查询(无子查询或UNION)。
PRIMARY:最外层查询(多表查询或子查询中的主查询)。
SUBQUERY:子查询(非关联子查询)。
DERIVED:派生表(FROM子句中的子查询结果)。
UNION:UNION操作中的第二个或后续查询。
table查询涉及的表名,若为派生表则显示为<derivedN>(N为派生表ID)。
type访问类型,性能从优到劣排序如下:
system:表仅有一行(系统表)。
const:通过主键或唯一索引匹配单行(如WHERE id=1)。
eq_ref:关联查询中,使用主键或唯一索引匹配单行(如JOIN操作)。
ref:非唯一索引匹配多行(如WHERE name='Alice')。
range:索引范围扫描(如WHERE id BETWEEN 1 AND 10)。
index:全索引扫描(覆盖索引时可能优于ALL)。
ALL:全表扫描(需优化)。
possible_keys可能使用的索引列表,若为NULL表示无可用索引。
key实际使用的索引,若为NULL表示未使用索引(需检查是否需添加索引或优化查询条件)。
key_len索引使用的字节数,可推断索引字段组合(如key_len=4可能仅使用INT类型主键)。
ref与索引比较的列或常量(如const表示固定值,test.orders.user_id表示关联字段)。
rows预估需扫描的行数,数值越大可能性能越差(需结合索引优化)。
Extra额外信息,常见值及含义:
Using index:使用覆盖索引(无需回表)。
Using where:在存储引擎检索后由Server层过滤数据。
Using temporary:使用临时表(需优化GROUP BY或ORDER BY)。
Using filesort:需额外排序(需优化ORDER BY或索引)。
Using join buffer:使用连接缓冲(需优化JOIN操作)。
根据执行计划结果,可针对性优化查询性能:
添加合适索引
场景:type=ALL(全表扫描)或possible_keys为NULL。
示例:若查询频繁按name过滤,可添加索引:ALTER TABLE users ADD INDEX idx_name (name);
避免全表扫描
场景:type=ALL且rows值过大。
方法:
添加索引覆盖查询条件。
重写查询(如避免SELECT *,仅查询必要字段)。
优化JOIN操作
场景:Extra=Using join buffer或type=ALL的表参与JOIN。
方法:
确保JOIN字段有索引(如外键字段)。
调整表顺序(小表驱动大表)。
使用STRAIGHT_JOIN强制连接顺序(谨慎使用)。
使用覆盖索引
场景:查询字段均包含在索引中(Extra=Using index)。
示例:若索引为(name, age),查询SELECT name, age FROM users可直接使用覆盖索引。
优化子查询
场景:select_type=SUBQUERY或DERIVED且性能差。
方法:
重写为JOIN操作。
使用EXISTS替代IN(大数据量时更高效)。
调整索引选择
场景:优化器选择非最优索引(如key非预期值)。
方法:
使用索引提示(如FORCE INDEX、USE INDEX)。
更新统计信息(ANALYZE TABLE users)。
通过系统分析执行计划并针对性优化,可显著提升MySQL查询性能,减少资源消耗。