update修改为merge(max+decode)
------------- 优化方法: 减少大表扫描次数采用max+decode方式
原sql语句:
UPDATE RKO_ACCT_STATUS A SET RMB_PAYMENT = (SELECT NVL(SUM(POSTING_AMT), 0) FROMRKOT_ACCT_PMT_PRIOR B WHERE B.ACCT = A.ACCT AND ORG = '242' AND POSTING_DATE BETWEENA.PRIOR_BILLING_DATE + 1 AND ADD_MONTHS(A.PRIOR_BILLING_DATE, 1) AND TXN_DATE <= (SELECT CASEWHEN USER_DATE_10=0 THEN NULL ELSE TO_DATE(USER_DATE_10, 'yyyyddd') END FROMRKOH_HAPS_AMBS_KD WHERE ACCT = A.ACCT AND ORG = 242 AND BATCH_DATE =TO_CHAR(LAST_DAY(A.PRIOR_BILLING_DATE),'yyyymmdd')) + 0.99999), USD_PAYMENT = (SELECTNVL(SUM(POSTING_AMT), 0) FROM RKOT_ACCT_PMT_PRIOR B WHERE B.ACCT = A.ACCT AND ORG = '241' ANDPOSTING_DATE BETWEEN A.PRIOR_BILLING_DATE + 1 AND ADD_MONTHS(A.PRIOR_BILLING_DATE, 1) ANDTXN_DATE <= (SELECT CASE WHEN USER_DATE_10=0 THEN NULL ELSE TO_DATE(USER_DATE_10, 'yyyyddd') ENDFROM RKOH_HAPS_AMBS_KD WHERE ACCT = A.ACCT AND ORG = 241 AND BATCH_DATE =TO_CHAR(LAST_DAY(A.PRIOR_BILLING_DATE),'yyyymmdd')) + 0.99999) WHERE TO_CHAR(A.PRIOR_BILLING_DATE,'yyyymm') = :B1;
格式化一下:
UPDATE RKO_ACCT_STATUS A
SET RMB_PAYMENT =
(SELECT NVL(SUM(POSTING_AMT),
0)
FROM RKOT_ACCT_PMT_PRIOR B
WHERE B.ACCT = A.ACCT
AND ORG = '242'
AND POSTING_DATE BETWEEN A.PRIOR_BILLING_DATE + 1 AND
ADD_MONTHS(A.PRIOR_BILLING_DATE,
1)
AND TXN_DATE <=
(SELECT CASE
WHEN USER_DATE_10 = 0 THEN
NULL
ELSE
TO_DATE(USER_DATE_10,
'yyyyddd')
END
FROM RKOH_HAPS_AMBS_KD
WHERE ACCT = A.ACCT
AND ORG = 242
AND BATCH_DATE = TO_CHAR(LAST_DAY(A.PRIOR_BILLING_DATE),
'yyyymmdd')) + 0.99999),
USD_PAYMENT =
(SELECT NVL(SUM(POSTING_AMT),
0)
FROM RKOT_ACCT_PMT_PRIOR B
WHERE B.ACCT = A.ACCT
AND ORG = '241'
AND POSTING_DATE BETWEEN A.PRIOR_BILLING_DATE + 1 AND
ADD_MONTHS(A.PRIOR_BILLING_DATE,
1)
AND TXN_DATE <=
(SELECT CASE
WHEN USER_DATE_10 = 0 THEN
NULL
ELSE
TO_DATE(USER_DATE_10,
'yyyyddd')
END
FROM RKOH_HAPS_AMBS_KD
WHERE ACCT = A.ACCT
AND ORG = 241
AND BATCH_DATE = TO_CHAR(LAST_DAY(A.PRIOR_BILLING_DATE),
'yyyymmdd')) + 0.99999)
WHERE TO_CHAR(A.PRIOR_BILLING_DATE,
'yyyymm') = :B1
;
原sql执行计划:
------------------------------------- 优化
create index ind_RKO_ACCT_date on RKO_ACCT_STATUS(PRIOR_BILLING_DATE) NOLOGGING parallel 20;
alter index ind_RKO_ACCT_date NOPARALLEL;
-------------------------------------------------------------------------------------------优化后sql
MERGE INTO RKO_ACCT_STATUS t
USING (SELECT /*+USE_HASH(a,b,c)*/ a.rowid rowids,
sum(DECODE(b.org,
242,
NVL(b.POSTING_AMT,
0))) counts,
sum(DECODE(b.org,
241,
NVL(b.POSTING_AMT,
0))) counts1
FROM RKOT_ACCT_PMT_PRIOR B,
RKOH_HAPS_AMBS_KD c,
RKO_ACCT_STATUS a
WHERE B.ACCT = A.ACCT
AND c.ACCT = A.ACCT
AND b.ORG = c.ORG
AND b.ORG IN (242,
241)
AND (b.POSTING_DATE BETWEEN A.PRIOR_BILLING_DATE + 1 AND
ADD_MONTHS(A.PRIOR_BILLING_DATE,
1))
AND (c.BATCH_DATE =
(TO_CHAR(LAST_DAY(A.PRIOR_BILLING_DATE),
'yyyymmdd')) + 0.99999)
AND b.TXN_DATE <= TO_DATE(USER_DATE_10,
'yyyyddd')
AND A.PRIOR_BILLING_DATE BETWEEN
to_date('2014-04-01',
'YYYY-MM-dd') AND
to_date('2014-05-31',
'YYYY-MM-dd')
GROUP BY a.rowid) t1
ON (t.rowid = t1.rowids)
WHEN MATCHED THEN
UPDATE
SET t.RMB_PAYMENT = t1.counts,
t.USD_PAYMENT = t1.counts1
;