为何需全表分组的SQL订单统计查询执行速度反而更快?
为什么看似更“笨”的SQL查询反而更快?
表结构
CREATE TABLE Users ( id INT, name TEXT ); CREATE TABLE Orders ( id INT, name TEXT, userId REFERENCES Users(id) );
查询需求
查询名为“bob”的用户及其所有订单总数,示例返回结果如下:
| User(id) | User(name) | Count(Orders) |
|---|---|---|
| 1 | Bob | 150 |
两种查询方案
方案一
SELECT * FROM Users JOIN (SELECT Bob.id, COUNT(*) FROM Orders JOIN (SELECT id FROM Users WHERE name = 'bob') Bob ON Orders.userId = Bob.id GROUP BY Bob.id) BobOrders ON BobOrders.id = Users.id;
执行分析结果:规划时间:0.301 ms / 执行时间:0.170 ms
方案二(语句更短但看似未优化)
SELECT * FROM Users JOIN (SELECT userId, COUNT(*) FROM Orders GROUP BY userId) MyData ON MyData.userId = Users.id AND Users.name = 'bob';
执行分析结果:规划时间:0.172 ms / 执行时间:0.106 ms
问题
为什么查询分析器显示第二个查询更快,它明明需要先对整个Orders表执行GROUP BY再过滤Users.id?
解答
这是因为数据库的查询优化器并不会严格按照你写SQL的顺序执行,它会对查询逻辑做等价改写,自动选择最优的执行路径。
具体到第二个查询,优化器会把Users.name = 'bob'这个过滤条件提前执行:
- 第一步:先从Users表快速定位到name='bob'的用户id
- 第二步:拿着这个id去Orders表筛选出userId匹配的订单记录
- 第三步:只对这些筛选后的订单做GROUP BY统计数量
而第一个查询虽然看起来是“先过滤再分组”,但嵌套了两层子查询,优化器需要花更多时间解析嵌套结构,反而增加了规划时间;另外,这种嵌套写法可能让优化器生成的执行计划效率不如第二个——实际上两个查询经过优化后的执行路径差异不大,但第二个的写法更简洁,优化器解析起来更快,执行开销也更小。
还要注意,这次测试的执行时间差异极小(都在0.2ms以内),主要是因为测试数据量较小。如果Orders表数据量极大,优化器最终会把两个查询的执行计划优化得几乎一致,但在小数据场景下,规划时间的差异会显得更突出。
内容的提问来源于stack exchange,提问作者Kernel James
相关产品推荐
相关产品推荐

