如何优化更新查询:
UPDATE frst_usage vfm1 SET
(vfm1.account_dn,
vfm1.usage_date,
vfm1.country,
vfm1.feature_name,
vfm1.hu_type,
vfm1.make,
vfm1.region,
vfm1.service_hits,
vfm1.maint_last_ts,
vfm1.accountdn_hashcode) = (
SELECT
(SELECT vst.account_dn FROM services_track vst WHERE vst.accountdn_hashcode = vrd1.account_dn_hashcode AND rownum = 1),
min(usage_date),
country,
feature_name,
hu_type,
make,
region,
service_hits,
SYSDATE,
account_dn_hashcode
FROM raw_data vrd1
WHERE vrd1.vin_hashcode = vfm1.vin_hashcode
AND vrd1.usage_date IS NOT NULL AND rownum = 1
GROUP BY account_dn, country, feature_name, hu_type, make, region, service_hits, vfm1.maint_last_ts, account_dn_hashcode
);
这些表在where条件中的所有列都有索引。
执行仍需要4个多小时。以下是解释计划
从执行计划中我可以看出选择是好的但是更新消耗了更多的时间资源,有没有办法可以优化它。
答案 0 :(得分:1)
我认为相关子查询可能是一个问题:
WHERE vrd1.vin_hashcode = vfm1.vin_hashcode
你应该尝试合并条款,它可能会对性能产生巨大影响 http://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_9016.htm
以下是与您类似的示例。 10k样本行,索引的所有列和收集的统计信息:
更新(16s)
SQL> update x1 set (v1, v2, v3, v4) =
2 (
3 select v1, v2, v3, min(v4)
4 from x2
5 where x1.nr = x2.nr
6 group by v1,v2,v3
7 );
9999 rows updated.
Elapsed: 00:00:16.56
Execution Plan
----------------------------------------------------------
Plan hash value: 3497322513
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 9999 | 859K| 1679K (5)| 05:35:59 |
| 1 | UPDATE | X1 | | | | |
| 2 | TABLE ACCESS FULL | X1 | 9999 | 859K| 40 (0)| 00:00:01 |
| 3 | SORT GROUP BY | | 1 | 88 | 41 (3)| 00:00:01 |
|* 4 | TABLE ACCESS FULL| X2 | 1 | 88 | 40 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("X2"."NR"=:B1)
合并(1,5s)
SQL> merge into x1 using (
2 select nr, v1, v2, v3, min(v4) v4
3 from x2
4 group by nr, v1,v2,v3
5 ) xx2
6 on (x1.nr = xx2.nr)
7 when matched then update set
8 x1.v1 = xx2.v1, x1.v2 = xx2.v2, x1.v3 = xx2.v3, x1.v4 = xx2.v4;
9999 rows merged.
Elapsed: 00:00:01.25
Execution Plan
----------------------------------------------------------
Plan hash value: 1113810112
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 9999 | 58M| | 285 (1)| 00:00:04 |
| 1 | MERGE | X1 | | | | | |
| 2 | VIEW | | | | | | |
|* 3 | HASH JOIN | | 9999 | 58M| | 285 (1)| 00:00:04 |
| 4 | TABLE ACCESS FULL | X1 | 9999 | 859K| | 40 (0)| 00:00:01 |
| 5 | VIEW | | 9999 | 57M| | 244 (1)| 00:00:03 |
| 6 | SORT GROUP BY | | 9999 | 859K| 1040K| 244 (1)| 00:00:03 |
| 7 | TABLE ACCESS FULL| X2 | 9999 | 859K| | 40 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("X1"."NR"="XX2"."NR")
答案 1 :(得分:0)
目标表上的索引会降低性能。在更新表之前禁用索引,并在更新完成后重建索引。
答案 2 :(得分:0)
能够使用以下查询解决此问题,现在解释计划看起来不错。
merge INTO FRST_USAGE vfu USING
(SELECT tmp1.*
FROM
(SELECT ROW_NUMBER() OVER (PARTITION BY tmp.vin_hash ORDER BY tmp.usage_date) AS rn,
tmp.*
FROM
(SELECT vrd.VIN_HASHCODE AS vin_hash,
vrd.ACCOUNT_DN_HASHCODE AS actdn_hash,
vst.ACCOUNT_DN AS actdn,
vrd.FEATURE_NAME AS feature,
vrd.MAKE AS make,
vrd.COUNTRY AS country,
vrd.HU_TYPE AS hu,
vrd.REGION AS region,
vrd.SERVICE_HITS AS hits,
MIN(vrd.USAGE_DATE) AS usage_date,
sysdate AS maintlastTs
FROM RAW_DATA vrd,
SERVICES_TRACK vst
WHERE vrd.ACCOUNT_DN_HASHCODE=vst.ACCOUNTDN_HASHCODE
GROUP BY vrd.VIN_HASHCODE,
vrd.ACCOUNT_DN_HASHCODE,
vst.ACCOUNT_DN,
vrd.FEATURE_NAME,
vrd.MAKE,
vrd.COUNTRY,
vrd.HU_TYPE,
vrd.REGION,
vrd.SERVICE_HITS,
sysdate
ORDER BY vrd.VIN_HASHCODE,
MIN(vrd.USAGE_DATE)
) tmp
)tmp1
WHERE tmp1.rn =1
) tmp2 ON (vfu.VIN_HASHCODE = tmp2.vin_hash)
WHEN matched THEN
UPDATE
SET vfu.ACCOUNTDN_HASHCODE=tmp2.actdn_hash,
vfu.account_dn =tmp2.actdn,
vfu.FEATURE_NAME =tmp2.feature,
vfu.MAKE =tmp2.make,
vfu.COUNTRY =tmp2.country,
vfu.HU_TYPE =tmp2.hu,
vfu.REGION =tmp2.region,
vfu.SERVICE_HITS =tmp2.hits,
vfu.usage_date =tmp2.usage_date,
vfu.MAINT_LAST_TS =tmp2.maintlastTs;
如果我可以对此进行更多优化,则允许建议。