MST

星途 面试题库

面试题:MySQL中如何通过执行计划分析来优化简单多表连接查询

假设有两个表`orders`(包含`order_id`、`customer_id`等字段)和`customers`(包含`customer_id`、`customer_name`等字段),要查询每个订单对应的客户姓名。请写出对应的SQL查询语句,并解释如何使用`EXPLAIN`关键字来分析执行计划,根据执行计划可能会采取哪些优化措施。
31.6万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试
  1. SQL查询语句
SELECT orders.order_id, customers.customer_name
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id;

上述SQL语句通过JOIN操作,根据orders表和customers表中的customer_id字段进行关联,从而获取每个订单对应的客户姓名。

  1. 使用EXPLAIN关键字分析执行计划
EXPLAIN SELECT orders.order_id, customers.customer_name
FROM orders
JOIN customers ON orders.customer_id = customers.customer_id;

执行上述EXPLAIN语句后,会得到一个结果集,通常包含以下几列(不同数据库可能略有差异):

  • id:标识查询中每个SELECT语句的标识符,用于确定执行顺序。
  • select_type:表示SELECT的类型,常见类型有SIMPLE(简单SELECT,不包含子查询或联合查询)。
  • table:表示该执行计划涉及的表。
  • partitions:如果表是分区表,显示相关分区信息,否则为NULL
  • type:表示连接类型,常见的有ALL(全表扫描)、index(索引扫描)、range(范围扫描)、ref(使用非唯一索引扫描)、eq_ref(使用唯一索引扫描,并且每个索引键值只匹配一条记录,通常出现在JOIN操作中)等。eq_refref等类型性能较好,ALL类型性能较差。
  • possible_keys:显示可能用于查询的索引。
  • key:实际使用的索引,如果为NULL,表示未使用索引。
  • key_len:表示使用索引的长度。
  • ref:显示哪个列或常量与索引进行比较。
  • rows:估计需要扫描的行数,该值越小越好。
  • filtered:表示存储引擎估计返回的数据行占表中数据行的百分比。
  1. 根据执行计划可能采取的优化措施
  • 添加索引
    • 如果typeALL,且possible_keys显示为空,说明没有使用索引。可以考虑在orders表和customers表的customer_id字段上添加索引,例如:
    CREATE INDEX idx_customers_customer_id ON customers(customer_id);
    CREATE INDEX idx_orders_customer_id ON orders(customer_id);
    
    这样在JOIN操作时,数据库可以使用索引来快速定位匹配的行,减少全表扫描,提高查询性能。
  • 优化表结构
    • 如果执行计划显示扫描的rows数过多,可能需要检查表结构是否合理。例如,是否存在冗余字段导致表数据量过大。如果存在,可以考虑进行规范化处理,减少数据冗余。
  • 调整JOIN顺序
    • 在复杂查询中,不同的表连接顺序可能会影响查询性能。可以通过STRAIGHT_JOIN关键字(部分数据库支持)来强制指定连接顺序。例如:
    SELECT STRAIGHT_JOIN orders.order_id, customers.customer_name
    FROM orders
    JOIN customers ON orders.customer_id = customers.customer_id;
    
    不过,使用STRAIGHT_JOIN需要谨慎,确保指定的顺序确实能提高性能,因为数据库优化器通常能够自动选择较好的连接顺序。