问题背景:
从一开始,SQL查询就被设计为声明式的:“获取什么”,而不是“如何获取”。数据库管理系统的优化器构建执行计划(execution plan),确定连接、过滤、扫描和索引使用的顺序。
问题:
没有理解执行计划,就无法解释为什么一个看似简单的查询执行得很慢,而复杂的查询却运行得很快。错误的计划可能会因为不必要的操作或索引使用不当而让服务器阻塞数小时。
解决方案:
分析工具包括类似于EXPLAIN、EXPLAIN ANALYZE(PostgreSQL)、SHOW EXPLAIN(MySQL)、Management Studio执行计划(SQL Server)的指令。借助这些工具,可以逐步查看查询的执行情况,包括读取了多少数据,使用了哪个索引,哪里进行了全表扫描(table scan),以及在哪里出现了延迟。
示例代码:
EXPLAIN ANALYZE SELECT * FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.status = 'shipped';
关键特点:
如果添加索引,查询一定会加速吗?
不一定!索引只会在其字段过滤明显限制返回行数时提供帮助。如果大多数记录符合条件,优化器可能会忽略索引。
示例:
-- 字段'gender'只有两个值——索引无效 CREATE INDEX idx_gender ON people(gender); SELECT * FROM people WHERE gender = 'M';
JOIN中表的顺序是否会影响执行结果?
不会,最终数据是相同的,但优化器可能会重新安排连接执行的顺序以提高性能。但如果编写了特定的JOIN或使用了“JOIN HINT”等提示,则顺序可能会影响执行的效率。
为什么要分析执行计划中的“Estimated rows”和“Actual rows”?
它们之间的差异可能表明表的统计信息过时或不准确,选择的计划并不理想——需要更新统计信息或重新审视查询结构。
-- PostgreSQL ANALYZE table_name; -- 更新统计信息
在项目中,分析师长时间抱怨报告的“卡顿”。含有五个JOIN的查询执行了25分钟。结果发现选择了完整扫描巨大表的计划,而非索引扫描,索引对的字段不对,统计信息一年未更新。
优点:
缺点:
进行了执行计划分析,新增了一个实际过滤字段的索引,更新了统计信息。查询时间减少到20秒,服务器负载降低了一个数量级。
优点:
缺点: