Oracle 中的合并花费了很多时间

问题描述 投票:0回答:1

我有一个包含 3600 万条记录的表,我需要在某些条件下更新字段,但每个查询需要 10 分钟,而且我有很多查询要运行:

     MERGE   INTO account USING ( SELECT id, COUNT( Account)  as numAcc
             FROM account  where Status = 'ACTIVATED' GROUP BY id) ba 
            ON (ba.id = b.id ) WHEN MATCHED THEN UPDATE SET b.numAcc = ba.numAcc;

上面的示例查询和其他查询看起来相同,但条件发生了变化,以下是解释

-------------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name                           | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT          |                                |    36M|   892M|       |   610K  (1)| 00:00:24 |
|   1 |  MERGE                   | ACCOUNT |       |       |       |            |          |
|   2 |   VIEW                   |                                |       |       |       |            |          |
|*  3 |    HASH JOIN             |                                |    36M|    19G|   511M|   610K  (1)| 00:00:24 |
|   4 |     VIEW                 |                                |   998K|   500M|       |   365K  (1)| 00:00:15 |
|   5 |      SORT GROUP BY       |                                |   998K|   502M|       |   365K  (1)| 00:00:15 |
|   6 |       VIEW               | VW_DAG_1                       |    25M|    12G|       |   365K  (1)| 00:00:15 |
|   7 |        SORT GROUP BY     |                                |    25M|  1025M|  1346M|   365K  (1)| 00:00:15 |
|*  8 |         TABLE ACCESS FULL| ACCOUNT |    25M|  1025M|       | 91408   (1)| 00:00:04 |
|   9 |     TABLE ACCESS FULL    | ACCOUNT |    36M|  2162M|       | 91501   (1)| 00:00:04 |
-------------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - access("BA"."ID"="B"."ID")
   8 - filter("Status "='ACTIVATED')
 
oracle performance merge sql-update
1个回答
0
投票

您可以尝试使用分析函数并在

id
伪列(实际上是指向行的指针)上进行关联,而不是在
ROWID
列上进行聚合和关联:

MERGE INTO account dst
USING (
  SELECT COUNT(CASE WHEN Status = 'ACTIVATE' THEN account END)
           OVER (PARTITION BY id) AS activated_count
  FROM   account
) src 
ON (
      dst.ROWID = src.ROWID
  AND src.activated_count > 0  -- Your query effectively includes this filter but I'm not sure
                               -- whether you intended that behaviour or not.
)
WHEN MATCHED THEN
  UPDATE SET dst.numAcc = src.activated_count;

您还可以检查该列是否已更改,如果没有更改,请跳过更新:

MERGE INTO account dst
USING (
  SELECT COUNT(CASE WHEN Status = 'ACTIVATE' THEN account END)
           OVER (PARTITION BY id) AS activated_count
  FROM   account
) src 
ON (
      dst.ROWID = src.ROWID
  AND src.activated_count > 0  -- Your query effectively includes this filter but I'm not sure
                               -- whether you intended that behaviour or not.
)
WHEN MATCHED THEN
  UPDATE
  SET   dst.numAcc =  src.activated_count
  WHERE dst.numAcc != src.activated_count;

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.