我正在对拥有数百万条记录的表进行多次更新,我尝试使用并行提示,但它不起作用,有时比没有并行提示更糟糕,
MERGE /*+ ENABLE_PARALLEL_DML PARALLEL(4) */ INTO Account a
USING (
SELECT id, COUNT(DISTINCT account) AS countAccount
FROM Account
WHERE accountStatus = 'Active'
GROUP BY id
) ba
ON (ba.id = a.id)
WHEN MATCHED THEN
UPDATE SET a.countAccount = ba.countAccount;
我有 4 核 CPU 和 16 GB 内存。 运行 select dbms_sqltune.report_sql_monitor 后得到以下结果,并从 SHOW PARAMETER parallel_max_servers 得到 parallel_max_servers 整数 160;
Global Information
------------------------------
Status : DONE
Instance ID : 1
Session : user (137:53518)
SQL ID : 6y1mrj5498fqd
SQL Execution ID : 16777218
Execution Started : 09/21/2024 18:43:11
First Refresh Time : 09/21/2024 18:43:11
Last Refresh Time : 09/21/2024 18:47:02
Duration : 231s
Module/Action : SQL Developer/-
Service : SYS$USERS
Program : SQL Developer
Global Stats
==================================================================================================
| Elapsed | Cpu | IO | Application | Other | Buffer | Read | Read | Write | Write |
| Time(s) | Time(s) | Waits(s) | Waits(s) | Waits(s) | Gets | Reqs | Bytes | Reqs | Bytes |
==================================================================================================
| 764 | 76 | 34 | 0.08 | 655 | 14M | 17898 | 4GB | 15180 | 2GB |
==================================================================================================
Parallel Execution Details (DOP=4 , Servers Allocated=8)
==================================================================================================================================================
| Name | Type | Server# | Elapsed | Cpu | IO | Application | Other | Buffer | Read | Read | Write | Write | Wait Events |
| | | | Time(s) | Time(s) | Waits(s) | Waits(s) | Waits(s) | Gets | Reqs | Bytes | Reqs | Bytes | (sample #) |
==================================================================================================================================================
| PX Coordinator | QC | | 0.09 | 0.00 | | 0.08 | 0.01 | 19 | | . | | . | |
| p000 | Set 1 | 1 | 192 | 14 | 0.14 | | 178 | 4M | 662 | 631MB | | . | |
| p001 | Set 1 | 2 | 169 | 13 | 0.15 | | 156 | 4M | 653 | 624MB | | . | |
| p002 | Set 1 | 3 | 168 | 13 | 0.14 | | 155 | 4M | 710 | 679MB | | . | |
| p003 | Set 1 | 4 | 180 | 15 | 0.15 | | 166 | 4M | 693 | 652MB | | . | |
| p004 | Set 2 | 1 | 14 | 5.38 | 8.44 | | | | 3792 | 444MB | 3792 | 444MB | |
| p005 | Set 2 | 2 | 13 | 5.49 | 7.96 | | | | 3811 | 447MB | 3811 | 447MB | |
| p006 | Set 2 | 3 | 14 | 5.21 | 8.30 | | | | 3782 | 443MB | 3782 | 443MB | |
| p007 | Set 2 | 4 | 14 | 5.41 | 8.49 | | | | 3795 | 445MB | 3795 | 445MB | |
==================================================================================================================================================
SQL Plan Monitoring Details (Plan Hash Value=2917601746)
========================================================================================================================================================================================================================
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Read | Read | Write | Write | Mem | Temp | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | Reqs | Bytes | Reqs | Bytes | (Max) | (Max) | (%) | (# samples) |
========================================================================================================================================================================================================================
| 0 | MERGE STATEMENT | | | | 1 | +231 | 9 | 8 | | | | | | | | |
| 1 | PX COORDINATOR | | | | 1 | +231 | 9 | 8 | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10005 | 13M | 27044 | 1 | +231 | 4 | 8 | | | | | | | | |
| 3 | MERGE | ACCOUNT | | | 218 | +14 | 4 | 4 | | | | | | | | |
| 4 | PX RECEIVE | | 13M | 27044 | 218 | +14 | 4 | 13M | | | | | | | | |
| 5 | PX SEND (ROWID RANDOM) | :TQ10004 | 13M | 27044 | 218 | +14 | 4 | 13M | | | | | | | | |
| 6 | VIEW | | | | 218 | +14 | 4 | 13M | | | | | | | | |
| 7 | HASH JOIN BUFFERED | | 13M | 27044 | 230 | +2 | 4 | 13M | 15180 | 2GB | 15180 | 2GB | 49M | 2G | | |
| 8 | PX RECEIVE | | 366K | 14469 | 1 | +2 | 4 | 366K | | | | | | | | |
| 9 | PX SEND HASH | :TQ10002 | 366K | 14469 | 1 | +2 | 4 | 366K | | | | | | | | |
| 10 | VIEW | | 366K | 14469 | 1 | +2 | 4 | 366K | | | | | | | | |
| 11 | SORT GROUP BY | | 366K | 14469 | 1 | +2 | 4 | 366K | | | | | 26M | | | |
| 12 | PX RECEIVE | | 366K | 14469 | 1 | +2 | 4 | 366K | | | | | | | | |
| 13 | PX SEND HASH | :TQ10001 | 366K | 14469 | 1 | +2 | 4 | 366K | | | | | | | | |
| 14 | SORT GROUP BY | | 366K | 14469 | 1 | +2 | 4 | 366K | | | | | 28M | | | |
| 15 | VIEW | VW_DAG_1 | 366K | 14469 | 1 | +2 | 4 | 366K | | | | | | | | |
| 16 | SORT GROUP BY | | 366K | 14469 | 2 | +1 | 4 | 366K | | | | | 29M | | | |
| 17 | PX RECEIVE | | 366K | 14469 | 1 | +2 | 4 | 731K | | | | | | | | |
| 18 | PX SEND HASH | :TQ10000 | 366K | 14469 | 1 | +2 | 4 | 731K | | | | | | | | |
| 19 | SORT GROUP BY | | 366K | 14469 | 1 | +2 | 4 | 731K | | | | | 319K | | | |
| 20 | PX BLOCK ITERATOR | | 672K | 12525 | 1 | +2 | 4 | 732K | | | | | | | | |
| 21 | TABLE ACCESS FULL | ACCOUNT | 672K | 12525 | 2 | +1 | 55 | 732K | 1359 | 1GB | | | | | | |
| 22 | PX RECEIVE | | 13M | 12566 | 13 | +2 | 4 | 13M | | | | | | | | |
| 23 | PX SEND HASH | :TQ10003 | 13M | 12566 | 13 | +2 | 4 | 13M | | | | | | | | |
| 24 | PX BLOCK ITERATOR | | 13M | 12566 | 13 | +2 | 4 | 13M | | | | | | | | |
| 25 | TABLE ACCESS FULL | ACCOUNT | 13M | 12566 | 13 | +2 | 55 | 13M | 1359 | 1GB | | | | | | |
========================================================================================================================================================================================================================
如果可能,请重新架构您的应用程序,以便不在表中存储聚合值。相反,当您
SELECT
数据时,根据需要导出值。
另一种优化是不更新所有行,而是只更新已更改的行:
MERGE /*+ ENABLE_PARALLEL_DML PARALLEL(4) */ INTO Account a
USING (
SELECT COUNT(DISTINCT
CASE accountStatus
WHEN 'Active'
THEN account
END
) OVER (PARTITION BY id) AS countAccount
FROM Account
) ba
ON ( a.ROWID = ba.ROWID
AND a.countAccount != ba.countAccount
AND ba.countAccount > 0
)
WHEN MATCHED THEN
UPDATE
SET a.countAccount = ba.countAccount;
另一种可能的解决方案可能是在表上放置一个触发器,当一行被
countAccount
ed 或 INSERT
d 或者 DELETE
修改 UPDATE
、id
时,重新计算 account
值或一行的 accountStatus
列。如果您在单个查询中进行大量修改,这可能需要是复合触发器。