MySQL 8.0执行计划type字段全解读:从全表扫描到索引查找的性能优化实战

MySQL 8.0 EXPLAIN执行计划type字段深度解析

SQL查询性能调优的核心工具是EXPLAIN,其中type字段直接反映MySQL访问数据的方式。从最差的全表扫描到最优的常量查询,type的值决定了查询的效率上限。本文逐级解析MySQL 8.0中type的所有取值,配合真实案例说明如何将type从ALL优化到ref甚至const。

type字段从差到优的完整排序

MySQL 8.0的type值按性能从差到优排列:

ALL < index < range < index_merge < index_subquery < unique_subquery < ref_or_null < ref < eq_ref < const < system

ALL:全表扫描——性能的绝对下限

type=ALL意味着MySQL必须遍历整张表的每一行来判断是否匹配WHERE条件。这是最差的访问方式。

EXPLAIN SELECT * FROM orders WHERE status = 'pending';
-- type: ALL, rows: 2500000

当status列没有索引时,MySQL扫描250万行。添加索引后:

ALTER TABLE orders ADD INDEX idx_status (status);
-- 再次EXPLAIN: type: ref, rows: 12000

扫描行数从250万降至1.2万,查询时间从1.8秒降至0.02秒。

index:全索引扫描——比ALL好但远非最优

type=index表示MySQL扫描了整个索引,而不是整个表数据。常见于查询只使用索引列且没有WHERE条件,或ORDER BY使用了索引但缺少过滤条件:

EXPLAIN SELECT id FROM orders ORDER BY created_at;
-- type: index, rows: 2500000, Extra: Using index

虽然Extra显示Using index(覆盖索引),但扫描了全索引250万条。当只需前N条时,加LIMIT:

EXPLAIN SELECT id FROM orders ORDER BY created_at LIMIT 100;
-- type: index, rows: 100

扫描行数从250万降至100。如果业务有过滤条件,优先加WHERE让type提升到range。

range:索引范围扫描——分页和日期查询的标准模式

type=range出现在索引列使用范围条件时,包括BETWEEN、>、<、IN等:

EXPLAIN SELECT * FROM orders
WHERE created_at BETWEEN '2026-07-01' AND '2026-08-01';
-- type: range, key: idx_created_at, rows: 380000

range是比较高效的方式,但要注意范围条件之后的列无法使用索引。复合索引(a, b, c)中,WHERE a=1 AND b>2只能用到a的等值和b的范围,c列无法继续走索引。

ref:非唯一索引等值查找——最常见的高效访问方式

type=ref出现在使用非唯一索引进行等值匹配时,是OLTP场景中最常见的type值:

EXPLAIN SELECT * FROM orders WHERE user_id = 10086;
-- type: ref, key: idx_user_id, rows: 15

ref的扫描行数取决于该索引值的区分度。如果user_id = 10086的记录有15条,MySQL读取15行即可。若区分度极低(如性别字段只有M/F两个值),ref的效率接近全表扫描。

优化手段:对低区分度字段,建立复合索引提升区分度:

ALTER TABLE orders ADD INDEX idx_status_created (status, created_at);
-- WHERE status='pending' AND created_at > '2026-07-01'
-- type: ref (status等值) + range (created_at范围)

eq_ref和const:最优访问方式

type=eq_ref出现在JOIN操作中使用主键或唯一索引等值匹配时,每次最多返回一行:

EXPLAIN SELECT o.* FROM orders o JOIN users u ON o.user_id = u.id
WHERE u.id = 10086;
-- users表: type: const
-- orders表: type: ref

type=const出现在WHERE条件使用主键或唯一索引等值匹配,且整个查询只有一行匹配:

EXPLAIN SELECT * FROM users WHERE id = 10086;
-- type: const, rows: 1

const是最高效的访问方式,MySQL在优化阶段就能确定结果,相当于将查询替换为常量。

实战:将一条慢查询的type从ALL优化到ref

原始SQL:

SELECT * FROM order_items
WHERE product_name LIKE '%手机%'
AND category_id = 5
AND created_at > '2026-01-01'
ORDER BY created_at DESC
LIMIT 20;
-- EXPLAIN: type=ALL, rows=5000000, 执行时间: 12.3s

问题分析:product_name的LIKE ‘%手机%’前缀模糊无法走索引,导致全表扫描。

优化步骤:

1. 去掉前缀模糊查询,改用全文索引或ES搜索product_name
2. 对category_id + created_at建复合索引

ALTER TABLE order_items ADD INDEX idx_cat_created (category_id, created_at);

SELECT * FROM order_items
WHERE category_id = 5
AND created_at > '2026-01-01'
AND product_name LIKE '%手机%'
ORDER BY created_at DESC
LIMIT 20;
-- EXPLAIN: type=ref, key=idx_cat_created, rows=8500, 执行时间: 0.15s

将product_name过滤放在最后,MySQL先用索引过滤category_id和created_at缩小范围,再在8500行中做LIKE匹配,查询速度从12.3秒降至0.15秒。type从ALL变为ref,是性能提升的根本原因。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/mysql80-zhi-xing-ji-hua-type-zi-duan-quan-jie-du-cong-quan/

(0)
小编小编
上一篇 16小时前
下一篇 16小时前

相关推荐