电话
400 9058 355
type=ALL表示全表扫描,性能最差;type=index是全索引扫描,略优于ALL;type=ref用于非唯一索引等值匹配,可能返回多行;type=eq_ref用于唯一索引等值匹配,每次最多返回1行;type=range用于索引范围扫描,如BETWEEN、>、IN等。
当 EXPLAIN 输出中 type 为 ALL,说明 MySQL 正在逐行读取整张表来匹配条件——没有用上任何索引。这在小表或 SELECT * + 无 WHERE 的场景下常见,但数据量稍大(比如 >1 万行)就会明显拖慢查询。
容易踩的坑:
user_id 是 VARCHAR,而 WHERE 里写成数字 WHERE user_id = 123),触发隐式转换导致索引失效WHERE YEAR(created_at) = 2025,无法走 created_at 索引(a,b,c) 建了索引
WHERE c = ?,无法命中type=index 不是“用了索引”,而是“全索引扫描”:MySQL 会遍历整个索引的 B+ 树叶子节点,而不是聚簇索引的数据页。它比 ALL 略快(尤其当索引比表小很多时),但仍是 O(n) 复杂度。
典型场景:
SELECT count(*) FROM t(无 WHERE),且存在非空索引(如主键)SELECT a FROM t ORDER BY a,而 a 上有索引但没 WHERE 条件SELECT a,b FROM t WHERE a > 10,(a,b) 是联合索引)注意:type=index 并不等于“高效”,它只是比 ALL 少读部分数据页;如果索引本身很大(例如长文本前缀索引),性能可能和 ALL 接近。
ref 表示使用了非唯一索引(或唯一索引的非前导列),返回多行可能;eq_ref 则表示使用了唯一索引(主键或 UNIQUE),且等值匹配,每次最多返回 1 行——这是连接查询中最理想的类型之一。
常见对比:
SELECT * FROM orders o JOIN users u ON o.user_id = u.id:若 u.id 是主键,则对 users 表是 eq_ref;若 o.user_id 只有普通索引,则对 orders 表是 ref
WHERE status = 'paid',status 是普通索引 → ref;WHERE id = 123,id 是主键 → eq_ref(单表查询中少见,多见于 JOIN)ref 可能因 NULL 值或范围条件退化为 range,而 eq_ref 几乎只出现在主键/唯一键等值 JOIN 场景range 表示 MySQL 使用索引定位一个连续区间,比如 BETWEEN、>、IN、LIKE 'abc%'。它比 ref 多读若干索引节点,但仍是“有界扫描”。
关键细节:
IN 列表过长(如几百项)可能导致优化器放弃走索引,降级为 ALL
LIKE 以通配符开头('%abc')无法用索引,不会出现 range
range:对 (a,b,c),WHERE a = 1 AND b > 2 AND c = 3 中,c 实际不参与索引查找(b 后已断开最左前缀)OR 条件会被重写为 UNION,各分支单独判断 type,整体 EXPLAIN 可能显示多个 range
真正影响性能的往往不是 type 字面值,而是实际扫描的索引行数(rows)和是否回表(Extra 里有没有 Using index)。同一个 range,查 10 行和查 10 万行,代价天壤之别。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...