Oracle Merge 语句“ON”与“UPDATE”条件在目标表上的性能

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

我在 ORACLE DB 中有 MERGE 查询。

MERGE INTO TABLE_1 T1
USING 
(
SELECT DISTINCT SMS_CENTER_ID FROM TABLE_2 T2 WHERE T2.DELIVERY_TIME >= ? AND T2.DELIVERY_TIME < ?) VIEW_1 
ON
(T1.SMS_CENTER_ID = VIEW_1.SMS_CENTER_ID AND T1.CREATE_TIME >= ? AND T1.CREATE_TIME < ?)

WHEN MATCHED THEN UPDATE
SET T1.DELETED = 1

问题:

  1. 以下更改能否提高大量数据的性能? (这样查询的持续时间长达5小时)?
MERGE INTO TABLE_1 T1
USING 
(
SELECT DISTINCT SMS_CENTER_ID FROM TABLE_2 T2 WHERE T2.DELIVERY_TIME >= ? AND T2.DELIVERY_TIME < ?) VIEW_1 
ON
(T1.SMS_CENTER_ID = VIEW_1.SMS_CENTER_ID)

WHEN MATCHED THEN UPDATE
SET T1.DELETED = 1
WHERE T1.CREATE_TIME >= ? AND T1.CREATE_TIME < ?
  1. 或者查询性能是否保持不变?

欢迎任何建议。

致以最诚挚的问候,谢谢。

目前,我正在寻找理论上可能的方法来解决问题。

sql oracle
1个回答
0
投票

以下更改能否提高大量数据的性能?

这可能会使情况变得更糟。


给定样本数据:

CREATE TABLE table_1 (sms_center_id, create_time, deleted) AS
SELECT 1, DATE '2024-01-01' + LEVEL - 1, 0
FROM   DUAL
CONNECT BY DATE '2024-01-01' + LEVEL - 1 < DATE '2025-01-01';

CREATE TABLE table_2 (sms_center_id, delivery_time) AS
SELECT 1, DATE '2024-01-01' FROM   DUAL;

(注:

table_1
有366行,
table_2
有1行。)

然后您可以确保两个表上的统计信息都是最新的:

BEGIN
  DBMS_STATS.GATHER_TABLE_STATS( USER, 'TABLE_1');
  DBMS_STATS.GATHER_TABLE_STATS( USER, 'TABLE_2');
END;
/

然后:

EXPLAIN PLAN FOR
MERGE INTO TABLE_1 T1
USING (
  SELECT DISTINCT SMS_CENTER_ID
  FROM   TABLE_2 T2
  WHERE  T2.DELIVERY_TIME >= DATE '2024-01-01'
  AND    T2.DELIVERY_TIME <  DATE '2025-01-01'
) VIEW_1 
ON (
      T1.SMS_CENTER_ID = VIEW_1.SMS_CENTER_ID
  AND T1.CREATE_TIME >= DATE '2024-01-01'
  AND T1.CREATE_TIME <  DATE '2024-01-01' + 200
)
WHEN MATCHED THEN UPDATE
  SET T1.DELETED = 1;

SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());

生成计划:

----------------------------------------------------------------------------------
| Id  | Operation              | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | MERGE STATEMENT        |         |   201 |   402 |     7  (15)| 00:00:01 |
|   1 |  MERGE                 | TABLE_1 |       |       |            |          |
|   2 |   VIEW                 |         |       |       |            |          |
|*  3 |    HASH JOIN           |         |   201 |  5226 |     7  (15)| 00:00:01 |
|   4 |     VIEW               |         |     1 |    13 |     4  (25)| 00:00:01 |
|   5 |      SORT UNIQUE       |         |     1 |    11 |     4  (25)| 00:00:01 |
|*  6 |       TABLE ACCESS FULL| TABLE_2 |     1 |    11 |     3   (0)| 00:00:01 |
|*  7 |     TABLE ACCESS FULL  | TABLE_1 |   201 |  2613 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - access("T1"."SMS_CENTER_ID"="VIEW_1"."SMS_CENTER_ID")
   6 - filter("T2"."DELIVERY_TIME">=TO_DATE(' 2024-01-01 00:00:00',
              'syyyy-mm-dd hh24:mi:ss') AND "T2"."DELIVERY_TIME"<TO_DATE(' 2025-01-01
              00:00:00', 'syyyy-mm-dd hh24:mi:ss'))
   7 - filter("T1"."CREATE_TIME"<TO_DATE(' 2024-07-19 00:00:00',
              'syyyy-mm-dd hh24:mi:ss') AND "T1"."CREATE_TIME">=TO_DATE(' 2024-01-01
              00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

和:

EXPLAIN PLAN FOR
MERGE INTO TABLE_1 T1
USING (
  SELECT DISTINCT SMS_CENTER_ID
  FROM   TABLE_2 T2
  WHERE  T2.DELIVERY_TIME >= DATE '2024-01-01'
  AND    T2.DELIVERY_TIME <  DATE '2025-01-01'
) VIEW_1 
ON (
      T1.SMS_CENTER_ID = VIEW_1.SMS_CENTER_ID
)
WHEN MATCHED THEN UPDATE
  SET   T1.DELETED = 1
  WHERE T1.CREATE_TIME >= DATE '2024-01-01'
  AND   T1.CREATE_TIME <  DATE '2024-01-01' + 200;

SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());

生成计划:

----------------------------------------------------------------------------------
| Id  | Operation              | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | MERGE STATEMENT        |         |   366 |  8052 |     7  (15)| 00:00:01 |
|   1 |  MERGE                 | TABLE_1 |       |       |            |          |
|   2 |   VIEW                 |         |       |       |            |          |
|*  3 |    HASH JOIN           |         |   366 |  9516 |     7  (15)| 00:00:01 |
|   4 |     VIEW               |         |     1 |    13 |     4  (25)| 00:00:01 |
|   5 |      SORT UNIQUE       |         |     1 |    11 |     4  (25)| 00:00:01 |
|*  6 |       TABLE ACCESS FULL| TABLE_2 |     1 |    11 |     3   (0)| 00:00:01 |
|   7 |     TABLE ACCESS FULL  | TABLE_1 |   366 |  4758 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - access("T1"."SMS_CENTER_ID"="VIEW_1"."SMS_CENTER_ID")
   6 - filter("T2"."DELIVERY_TIME">=TO_DATE(' 2024-01-01 00:00:00',
              'syyyy-mm-dd hh24:mi:ss') AND "T2"."DELIVERY_TIME"<TO_DATE(' 2025-01-01
              00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

第一个计划,其中过滤器位于

ON
子句中,有一个附加过滤器并在 201 行上运行。第二个计划没有额外的过滤器,并且对所有 366 行进行操作,因此它将生成更多的撤消/重做日志,对所有可能的匹配项进行操作,而不仅仅是这些行的所需子集。

小提琴

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