面试题答案
一键面试1. 了解各字段含义
- id:标识查询中SELECT语句的顺序。如果id相同,执行顺序由上至下;如果id不同,id值越大优先级越高,越先执行。
- select_type:表示查询类型,常见的有
SIMPLE
(简单查询,不包含子查询或UNION)、PRIMARY
(最外层查询)、SUBQUERY
(子查询)等。不同类型的查询优化方式有别。 - table:显示查询涉及的表名。
- partitions:显示表分区信息,如果表未分区则为
NULL
。 - type:显示连接类型,常见的有
ALL
(全表扫描)、index
(索引扫描)、range
(范围扫描)、ref
(使用非唯一索引扫描)、eq_ref
(使用唯一索引扫描)、const
(常量连接,表最多返回一行数据)。连接类型从优到差一般为:system
/const
>eq_ref
>ref
>range
>index
>ALL
。 - possible_keys:显示可能使用到的索引。
- key:显示实际使用的索引,如果为
NULL
,表示未使用索引。 - key_len:显示索引使用的字节数,可判断索引使用是否完整。
- ref:显示哪些列或常量与索引一起被使用。
- rows:估计需要扫描的行数,该值越小越好。
- filtered:表示表中满足条件的行占总行数的百分比。
- Extra:额外信息,例如
Using temporary
(使用临时表,通常意味着查询性能较差)、Using filesort
(文件排序,性能较差)、Using index
(使用覆盖索引,性能较好)等。
2. 优化方法及举例
2.1 避免全表扫描(ALL类型)
- 问题:假设存在
orders
表(包含order_id
,customer_id
,order_date
等字段)和customers
表(包含customer_id
,customer_name
等字段),进行如下查询:
EXPLAIN SELECT *
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id;
若type
为ALL
,表示对orders
表进行全表扫描,性能较差。
- 优化:为
orders
表的customer_id
字段添加索引。
CREATE INDEX idx_customer_id ON orders(customer_id);
再次执行EXPLAIN
,type
可能变为ref
,性能提升。
2.2 合理使用索引(关注key和possible_keys)
- 问题:对于上述查询,如果
possible_keys
显示有多个索引可使用,但key
显示使用的不是最优索引。例如,orders
表有idx_customer_id
和idx_order_date
索引,而实际查询应基于customer_id
关联,却使用了idx_order_date
索引。 - 优化:通过添加
FORCE INDEX (idx_customer_id)
来强制使用正确索引。
EXPLAIN SELECT *
FROM orders FORCE INDEX (idx_customer_id)
JOIN customers ON orders.customer_id = customers.customer_id;
2.3 减少临时表和文件排序(关注Extra字段)
- 问题:如果
Extra
中出现Using temporary
和Using filesort
,例如在对orders
表按order_date
排序并分组查询时:
EXPLAIN SELECT order_date, COUNT(*)
FROM orders
GROUP BY order_date
ORDER BY order_date;
- 优化:为
order_date
字段添加索引,让查询可以利用索引直接完成排序和分组。
CREATE INDEX idx_order_date ON orders(order_date);
再次执行EXPLAIN
,Extra
字段中可能不再出现Using temporary
和Using filesort
。