案例说明
更新时间: 2026-04-02 15:20:22
阅读 25
相关SQL语句说明
本案例中,使用如下的查询语句,在优化前,涉及到多表关联和子查询以及分页,使用了select * ,性能差,不可控:
SELECT *
FROM (
SELECT *
FROM order_main om
LEFT JOIN order_detail od ON om.order_id = od.order_id
WHERE om.order_status IN (1, 2, 3)
AND om.create_time >= '2025-01-01 00:00:00'
AND om.user_id IN (
SELECT user_id
FROM user_info
WHERE user_level >= 2
AND is_active = 1
)
) AS order_full
LEFT JOIN product_info pi ON order_full.product_id = pi.product_id
WHERE pi.is_on_sale = 1
ORDER BY order_full.create_time DESC, order_full.order_id DESC
LIMIT 0, 20;
代码优化说明
样例代码如下:
代码块
SELECT
order_full.order_id,
order_full.user_id,
order_full.product_id,
order_full.order_status,
order_full.create_time,
-- ... 其他需要的字段
pi.product_name,
pi.is_on_sale
FROM (
SELECT
om.order_id,
om.user_id,
od.product_id, -- 假设 product_id 来自 order_detail
om.order_status,
om.create_time,
-- ... 其他需要的字段
ROW_NUMBER() OVER (ORDER BY om.create_time DESC, om.order_id DESC) AS rn
FROM order_main om
-- 假设 order_main 表有按日期分区的字段 dt,根据 create_time 补充过滤
LEFT JOIN order_detail od ON om.order_id = od.order_id
INNER JOIN user_info ui ON om.user_id = ui.user_id
AND ui.user_level >= 2
AND ui.is_active = 1
WHERE om.order_status IN (1, 2, 3)
AND om.create_time >= '2025-01-01 00:00:00'
-- 根据实际分区键调整,例如假设分区字段为 dt,且与 create_time 同日期
AND om.dt >= '2025-01-01'
) AS order_full
LEFT JOIN product_info pi ON order_full.product_id = pi.product_id
AND pi.is_on_sale = 1 -- 过滤条件下推
WHERE order_full.rn <= 20 -- 提前限制数据量
ORDER BY order_full.create_time DESC, order_full.order_id DESC;
优化点说明:
使用显式字段列表代替 SELECT *,减少I/O和Shuffle数据量(请根据实际需求替换字段名)。
将 IN 子查询改为 JOIN,可能利用MapJoin或更优的执行计划。
补充了假设的分区过滤条件
om.dt >= '2025-01-01',请根据实际分区键调整。将 product_info 的过滤条件下推到 JOIN 条件中。
使用子查询提前进行排序和分页,减少参与最终全局排序的数据量。
代码优化效果截图

文档反馈
以上内容对您是否有帮助?