MST

星途 面试题库

面试题:MySQL中如何利用EXPLAIN优化多表连接查询性能

假设有三张表A、B、C,它们之间存在关联关系,现有一个涉及这三张表的复杂查询语句。请描述如何使用EXPLAIN来分析这个查询,找出可能存在性能问题的点,并说明如何优化以提升查询性能。
41.5万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试
  1. 使用EXPLAIN分析查询
    • 在查询语句前加上EXPLAIN关键字,例如:EXPLAIN SELECT * FROM A JOIN B ON A.id = B.a_id JOIN C ON B.id = C.b_id WHERE A.some_column = 'value';
    • 执行添加EXPLAIN后的查询,查看输出结果。EXPLAIN输出的常见列及其含义:
      • id:标识查询中每个SELECT语句的标识符,用于确定执行顺序。
      • select_type:表示SELECT的类型,如SIMPLE(简单SELECT,不包含子查询或联合查询)、PRIMARY(最外层SELECT)等。
      • table:显示对应行正在访问的表。
      • partitions:如果表是分区表,显示查询访问的分区。
      • type:表示表的连接类型,常见类型有ALL(全表扫描)、index(索引扫描)、range(范围扫描)、ref(使用非唯一索引进行连接)、eq_ref(使用唯一索引进行连接)等,ALL性能最差,eq_ref性能较好。
      • possible_keys:显示可能用于连接的索引。
      • key:实际使用的索引,如果为NULL,则表示没有使用索引。
      • key_len:表示使用索引的长度,可用于评估索引使用的效率。
      • ref:显示哪些列或常量与索引进行比较。
      • rows:估计需要扫描的行数,该值越小越好。
      • filtered:表示表中满足过滤条件的行的百分比。
  2. 找出可能存在性能问题的点
    • 全表扫描(typeALL:如果某个表的typeALL,说明查询在该表上进行了全表扫描,这通常会导致性能低下,特别是对于大表。
    • 未使用索引(keyNULL:当possible_keys列出了索引,但keyNULL时,说明虽然有可用索引,但查询没有使用它,可能是查询条件或索引设计不合理。
    • 过多的扫描行数(rows值过大):如果rows值很大,意味着需要扫描大量数据,可能影响性能。
    • 低过滤百分比(filtered值过小):如果filtered值很小,说明在表扫描后只有很少的行满足条件,可能需要优化过滤条件。
  3. 优化以提升查询性能
    • 添加合适的索引
      • 分析查询条件,在连接条件(如ON子句中的条件)和过滤条件(如WHERE子句中的条件)涉及的列上添加索引。例如,如果A.id用于连接B表,在A.idB.a_id上添加索引;如果A.some_column用于过滤,在A.some_column上添加索引。但注意索引并非越多越好,过多索引会增加插入、更新操作的开销。
    • 优化连接顺序
      • 根据EXPLAIN输出的rowstype信息,尝试调整表的连接顺序。通常先连接小表,再连接大表,可以减少中间结果集的大小。例如,如果表A较小,表BC较大,可以尝试先连接AB,再连接C
    • 优化查询条件
      • 确保过滤条件使用的列上有索引,避免在索引列上使用函数或操作符,例如WHERE UPPER(A.some_column) = 'VALUE'会导致索引失效,应改为WHERE A.some_column = 'value'
      • 合理使用ANDOR,如果OR连接的条件中有列没有索引,可能导致全表扫描,尽量将OR条件转换为IN子句或使用联合索引来解决。
    • 分区表优化
      • 如果表数据量巨大,可以考虑使用分区表。根据查询条件,合理选择分区键,使查询能够快速定位到相关分区,减少扫描的数据量。例如,如果经常按日期范围查询,可以按日期进行分区。