执行计划解释
MySQL执行计划中的type和extra列是分析查询性能的关键指标:
type列解析
type列表示MySQL访问表数据的方式,按效率从高到低排序如下:
system:表仅一行数据(系统表特例)
const:通过主键或唯一索引等值查询,最多返回一行
eq_ref:表连接时使用主键或唯一索引关联(如JOIN ... ON a.id=b.id)
ref:使用非唯一索引的等值查询
range:索引范围扫描(BETWEEN、IN等操作)
index:全索引扫描(比ALL快,但仍需遍历索引树)
ALL:全表扫描(性能最差)
extra列详解
extra列显示查询执行的附加信息,常见值包括:
Using index:覆盖索引,无需回表
Using where:存储引擎返回数据后需服务器层过滤
Using filesort:外部排序(需优化ORDER BY)
Using temporary:创建临时表(常见于GROUP BY)
Using index condition:使用索引条件下推(ICP)优化:表示查询部分利用了索引但需要进一步筛选数据
Using join buffer:使用连接缓存
优化建议
尽量使type达到ref或range级别
通过覆盖索引(Using index)避免回表
避免出现Using filesort和Using temporary
复合索引需遵循最左前缀原则
执行计划示例
1.const (主键/唯一索引等值查询)
-- 主键精确匹配 SELECT * FROM users WHERE id = 1; -- 唯一索引精确匹配 SELECT * FROM products WHERE product_code = 'A1001';
2.eq_ref (主键/唯一索引关联)
-- 多表JOIN时使用主键关联 SELECT * FROM orders o JOIN users u ON o.user_id = u.id; -- u.id是users表主键-- 使用唯一索引关联 SELECT * FROM orders o JOIN products p ON o.product_id = p.unique_code; -- p.unique_code是唯一索引
3.ref (非唯一索引等值查询)
-- 普通索引查询 SELECT * FROM orders WHERE status = 'paid'; -- status字段有普通索引-- 多列索引非最左列查询 SELECT * FROM products WHERE category_id = 5; -- 索引是(category_id, price)
4.range (索引范围扫描)
-- 范围查询 SELECT * FROM orders WHERE create_time BETWEEN '2025-01-01' AND '2025-12-31';-- IN查询 SELECT * FROM users WHERE age IN (20, 30, 40);-- 大于/小于查询 SELECT * FROM products WHERE price > 1000;
5.index (全索引扫描)
-- 查询所有索引列值 SELECT indexed_column FROM table_with_index;-- 覆盖索引查询 SELECT id, name FROM users; -- (id,name)有联合索引
6.ALL (全表扫描)
-- 无索引列查询 SELECT * FROM logs WHERE message LIKE '%error%';-- 索引失效的查询 SELECT * FROM products WHERE YEAR(create_time) = 2025;-- 小表查询(优化器认为全表更快) SELECT * FROM config_table; -- 表中只有10条记录
extra示例
Using index:覆盖索引,无需回表
-- 查询字段全部在索引中 SELECT id FROM users WHERE id > 100; -- id是主键-- 复合索引覆盖查询 SELECT name, age FROM employees WHERE dept_id = 5; -- (dept_id, name, age)有联合索引
Using where:存储引擎返回数据后需数据库服务器层过滤
-- 非索引列条件过滤 SELECT * FROM orders WHERE total_amount > 1000 AND status = 'paid'; -- 仅total_amount有索引-- 索引列使用函数导致失效 SELECT * FROM products WHERE YEAR(create_time) = 2025; -- create_time有索引
Using filesort:外部排序(需优化ORDER BY)
-- 非索引列排序 SELECT * FROM users ORDER BY register_date; -- register_date无索引-- 索引列非常规排序 SELECT * FROM products WHERE category = 'electronics' ORDER BY price DESC; -- (category)有索引但price无索引
Using temporary:创建临时表(常见于GROUP BY)
-- 非索引列GROUP BY SELECT department, COUNT(*) FROM employees GROUP BY department; -- department无索引-- 复杂DISTINCT操作 SELECT DISTINCT(name), age FROM students;
Using index condition:使用索引条件下推(ICP)优化
-- 复合索引部分条件过滤 SELECT * FROM orders WHERE user_id = 100 AND order_date > '2025-01-01'; -- (user_id, order_date)有索引-- 索引列范围查询+非索引列过滤 SELECT * FROM logs WHERE create_time BETWEEN '2025-01-01' AND '2025-12-31' AND message LIKE '%error%'; -- create_time有索引
Using join buffer:使用连接缓存
-- 大表JOIN无索引列 SELECT * FROM orders o JOIN customers c ON o.customer_name = c.name; -- name无索引-- 多表复杂JOIN SELECT * FROM table_a a JOIN table_b b ON a.col1 = b.col2 JOIN table_c c ON b.col3 = c.col4;
