面试题答案
一键面试- 使用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:表示表中满足过滤条件的行的百分比。
- id:标识查询中每个
- 在查询语句前加上
- 找出可能存在性能问题的点:
- 全表扫描(
type
为ALL
):如果某个表的type
为ALL
,说明查询在该表上进行了全表扫描,这通常会导致性能低下,特别是对于大表。 - 未使用索引(
key
为NULL
):当possible_keys
列出了索引,但key
为NULL
时,说明虽然有可用索引,但查询没有使用它,可能是查询条件或索引设计不合理。 - 过多的扫描行数(
rows
值过大):如果rows
值很大,意味着需要扫描大量数据,可能影响性能。 - 低过滤百分比(
filtered
值过小):如果filtered
值很小,说明在表扫描后只有很少的行满足条件,可能需要优化过滤条件。
- 全表扫描(
- 优化以提升查询性能:
- 添加合适的索引:
- 分析查询条件,在连接条件(如
ON
子句中的条件)和过滤条件(如WHERE
子句中的条件)涉及的列上添加索引。例如,如果A.id
用于连接B
表,在A.id
和B.a_id
上添加索引;如果A.some_column
用于过滤,在A.some_column
上添加索引。但注意索引并非越多越好,过多索引会增加插入、更新操作的开销。
- 分析查询条件,在连接条件(如
- 优化连接顺序:
- 根据
EXPLAIN
输出的rows
和type
信息,尝试调整表的连接顺序。通常先连接小表,再连接大表,可以减少中间结果集的大小。例如,如果表A
较小,表B
和C
较大,可以尝试先连接A
和B
,再连接C
。
- 根据
- 优化查询条件:
- 确保过滤条件使用的列上有索引,避免在索引列上使用函数或操作符,例如
WHERE UPPER(A.some_column) = 'VALUE'
会导致索引失效,应改为WHERE A.some_column = 'value'
。 - 合理使用
AND
和OR
,如果OR
连接的条件中有列没有索引,可能导致全表扫描,尽量将OR
条件转换为IN
子句或使用联合索引来解决。
- 确保过滤条件使用的列上有索引,避免在索引列上使用函数或操作符,例如
- 分区表优化:
- 如果表数据量巨大,可以考虑使用分区表。根据查询条件,合理选择分区键,使查询能够快速定位到相关分区,减少扫描的数据量。例如,如果经常按日期范围查询,可以按日期进行分区。
- 添加合适的索引: