MST

星途 面试题库

面试题:MySQL性能剖析工具之EXPLAIN的深入应用

对于复杂的多表关联查询,使用EXPLAIN分析执行计划时,如何通过执行计划中的信息(如id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、Extra等字段)来优化SQL查询性能?请举例说明。
16.8万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试

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;

typeALL,表示对orders表进行全表扫描,性能较差。

  • 优化:为orders表的customer_id字段添加索引。
CREATE INDEX idx_customer_id ON orders(customer_id);

再次执行EXPLAINtype可能变为ref,性能提升。

2.2 合理使用索引(关注key和possible_keys)

  • 问题:对于上述查询,如果possible_keys显示有多个索引可使用,但key显示使用的不是最优索引。例如,orders表有idx_customer_ididx_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 temporaryUsing 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);

再次执行EXPLAINExtra字段中可能不再出现Using temporaryUsing filesort