面试题答案
一键面试优化方案
- 分析子查询:若子查询是相关子查询,尝试将其改写为连接查询。例如,假设有如下子查询:
SELECT column1, (SELECT COUNT(*) FROM other_table WHERE other_table.id = main_table.id) AS count
FROM main_table;
可改写为连接查询:
SELECT main_table.column1, COUNT(other_table.id) AS count
FROM main_table
LEFT JOIN other_table ON main_table.id = other_table.id
GROUP BY main_table.column1, main_table.id;
- 聚合函数优化:如果聚合函数操作的数据量非常大,可以考虑在中间表或索引上进行聚合。例如,对于
SUM
聚合,若数据量巨大,可先创建一个包含预计算SUM
的中间表,查询时直接从中间表获取数据。 - 索引优化:
- 检查查询涉及的列上是否有合适的索引。例如,在上述查询中,如果
main_table.id
和other_table.id
列没有索引,添加索引:
- 检查查询涉及的列上是否有合适的索引。例如,在上述查询中,如果
CREATE INDEX idx_main_table_id ON main_table(id);
CREATE INDEX idx_other_table_id ON other_table(id);
- 使用
EXPLAIN
分析:在优化前后分别使用EXPLAIN
关键字来查看执行计划,根据执行计划进一步调整优化策略。例如:
EXPLAIN SELECT column1, (SELECT COUNT(*) FROM other_table WHERE other_table.id = main_table.id) AS count
FROM main_table;
优化后:
EXPLAIN SELECT main_table.column1, COUNT(other_table.id) AS count
FROM main_table
LEFT JOIN other_table ON main_table.id = other_table.id
GROUP BY main_table.column1, main_table.id;
优化前后执行计划差异及原理
- 子查询改连接查询:
- 优化前:子查询可能会导致数据库对外部查询的每一行都执行一次子查询,这是一种嵌套循环的方式,数据量较大时效率很低。例如,外部查询有
n
行,子查询对每一行执行一次,整体复杂度是O(n * m)
,其中m
是子查询结果集行数。 - 优化后:连接查询通过
JOIN
操作将两个表的数据在一次操作中关联起来,数据库可以使用更高效的算法,如哈希连接或嵌套循环连接(在有合适索引时),整体复杂度可能降低到O(n + m)
。
- 优化前:子查询可能会导致数据库对外部查询的每一行都执行一次子查询,这是一种嵌套循环的方式,数据量较大时效率很低。例如,外部查询有
- 索引优化:
- 优化前:如果没有索引,数据库在进行表连接或条件筛选时需要全表扫描,这在数据量较大时非常耗时。例如,在上述查询中,如果没有
main_table.id
和other_table.id
的索引,连接操作需要逐行比较两个表中的id
列,效率低下。 - 优化后:添加索引后,数据库可以利用索引快速定位到符合条件的数据行,大大减少了扫描的数据量,提高了查询效率。例如,在连接操作中,通过索引可以快速定位到匹配的
id
,而不需要全表扫描。
- 优化前:如果没有索引,数据库在进行表连接或条件筛选时需要全表扫描,这在数据量较大时非常耗时。例如,在上述查询中,如果没有
- 聚合函数优化:
- 优化前:对大量数据直接进行聚合操作,数据库需要处理大量数据行,占用较多内存和CPU资源。
- 优化后:通过中间表或索引上的预计算聚合,查询时只需获取预计算结果,减少了实时计算量,提高了查询效率。