前段时间,有个同事找我,让我帮忙优化一下DML SQL语句,说是update更新很慢,一分钟值更新260条数据,但是里面有20W以上的数据需要更新。
原SQL(F5执行效率Cost 24099646913):
UPDATE jb_cost_estimation_customer e
SET (total_income, income, customer_price) =
(SELECT SUM(sc.cost) AS total_income,
round(SUM(sc.cost / (1 + nvl(scr2.remark_text, 0) / 100)), 2) AS income,
rf.shipment_refnum_value AS customer_price
FROM jb_cost_estimation_customer ec ---
LEFT JOIN shipment_cost_remark scr
ON ec.shipment_gid = scr.remark_text
AND scr.remark_qual_gid = 'JBL.COST_应付运单号'
LEFT JOIN shipment_cost sc ---
ON scr.shipment_cost_seqno = sc.shipment_cost_seqno
LEFT JOIN shipment s
ON s.shipment_gid = sc.shipment_gid
LEFT JOIN shipment_refnum rf
ON s.shipment_gid = rf.shipment_gid
AND rf.shipment_refnum_qual_gid = 'JBL.单价'
LEFT JOIN shipment_cost_remark scr2 --
ON scr2.shipment_cost_seqno = scr.shipment_cost_seqno
AND scr2.remark_qual_gid = 'JBL.COST_税率'
WHERE ec.shipment_gid = e.shipment_gid
--1=1
GROUP BY rf.shipment_refnum_value, ec.shipment_gid);
其中Select语句的条数统计如下:
SELECT COUNT(1) --215253
FROM (SELECT SUM(sc.cost) AS total_income,
round(SUM(sc.cost / (1 + nvl(scr2.remark_text, 0) / 100)), 2) AS income,
rf.shipment_refnum_value AS customer_price,
ec.shipment_gid
FROM jb_cost_estimation_customer ec ---
LEFT JOIN shipment_cost_remark scr
ON ec.shipment_gid = scr.remark_text
AND scr.remark_qual_gid = 'JBL.COST_应付运单号'
LEFT JOIN shipment_cost sc ---
ON scr.shipment_cost_seqno = sc.shipment_cost_seqno
LEFT JOIN shipment s
ON s.shipment_gid = sc.shipment_gid
LEFT JOIN shipment_refnum rf
ON s.shipment_gid = rf.shipment_gid
AND rf.shipment_refnum_qual_gid = 'JBL.单价'
LEFT JOIN shipment_cost_remark scr2 --
ON scr2.shipment_cost_seqno = scr.shipment_cost_seqno
AND scr2.remark_qual_gid = 'JBL.COST_税率'
--WHERE ec.shipment_gid = e.shipment_gid
--1=1
GROUP BY rf.shipment_refnum_value, ec.shipment_gid) e;
首先我根据表关联的逻辑适当调整SQL(F5执行效率Cost 8672729249,经调整Cost下降两位数)
UPDATE jb_cost_estimation_customer e
SET (total_income, income, customer_price) =
(SELECT SUM(sc.cost) AS total_income,
round(SUM(sc.cost / (1 + nvl(scr2.remark_text, 0) / 100)), 2) AS income,
rf.shipment_refnum_value AS customer_price
FROM jb_cost_estimation_customer ec,
shipment_cost_remark scr,
shipment_cost_remark scr2,
shipment_cost sc,
shipment_refnum rf
WHERE ec.shipment_gid = scr.remark_text
AND scr.remark_qual_gid = 'JBL.COST_应付运单号'
AND scr.shipment_cost_seqno = scr2.shipment_cost_seqno
AND scr2.remark_qual_gid = 'JBL.COST_税率'
AND scr.shipment_cost_seqno = sc.shipment_cost_seqno
AND sc.shipment_gid = rf.shipment_gid
AND rf.shipment_refnum_qual_gid = 'JBL.单价'
---------------------------------------------------------------------------
AND ec.shipment_gid = e.shipment_gid
--------------------------------------------------------------------
GROUP BY rf.shipment_refnum_value, ec.shipment_gid);
方案1: 使用Merge语句,其F5执行效率Cost 157068
方案2:使用批量 forall ,不限制更新条数耗时 11.156s