You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将带SUM和多WHERE条件的子查询改写为JOIN结构以提升查询性能

性能问题根源

原查询使用了相关子查询逻辑:外层每返回1行t表的记录,都要对内层tasks_sub表执行一次独立的匹配求和计算,当表数据量较大时,整体时间复杂度为O(n²),是性能瓶颈的核心原因。

优化后的JOIN版本SQL

我们可以先做一次预聚合计算好所有符合条件的分组求和值,再和主表关联,仅需要两次全表扫描(有索引时甚至不需要全表)即可完成计算,性能提升显著:

SELECT 
    t.*,
    COALESCE(s.sum_delivered, 0) AS sum_delivered
FROM tasks t
LEFT JOIN (
    SELECT
        `table`,
        proces_id,
        order_id,
        `index`,
        SUM(delivered) AS sum_delivered
    FROM tasks
    GROUP BY `table`, proces_id, order_id, `index`
) s ON (
    (s.`table` = t.`table` AND s.proces_id = t.proces_id) 
    OR s.order_id = t.order_id
) AND s.`index` = t.`index`;

如果你的数据库对JOIN中的OR条件优化不好,可以进一步拆分为两个聚合子查询分别匹配两个OR分支,再合并结果,避免OR导致的索引失效:

SELECT
    t.*,
    COALESCE(s1.sum_delivered, 0) + COALESCE(s2.sum_delivered, 0) AS sum_delivered
FROM tasks t
LEFT JOIN (
    SELECT `table`, proces_id, `index`, SUM(delivered) AS sum_delivered
    FROM tasks
    GROUP BY `table`, proces_id, `index`
) s1 ON s1.`table` = t.`table` AND s1.proces_id = t.proces_id AND s1.`index` = t.`index`
LEFT JOIN (
    SELECT order_id, `index`, SUM(delivered) AS sum_delivered
    FROM tasks
    GROUP BY order_id, `index`
) s2 ON s2.order_id = t.order_id AND s2.`index` = t.`index`;

注意:如果存在同时满足两个OR分支的记录,第二种写法会重复计算,需要根据你的业务逻辑判断是否需要去重,原查询的逻辑是不会重复计算的,所以如果有重叠场景,可以在预聚合阶段加上distinct逻辑处理

额外索引优化建议

要进一步提升性能,可以给tasks表建立如下覆盖索引,避免回表查询:

  • 针对第一个优化方案:INDEX idx_task_query (table, proces_id, order_id, index, delivered)
  • 针对第二个拆分OR的优化方案:建立两个索引
    • INDEX idx_group1 (table, proces_id, index, delivered)
    • INDEX idx_group2 (order_id, index, delivered)

内容的提问来源于stack exchange,提问作者Michał Moskal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 04:06:00