我在 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
问题:
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 < ?
欢迎任何建议。
致以最诚挚的问候,谢谢。
目前,我正在寻找理论上可能的方法来解决问题。
以下更改能否提高大量数据的性能?
这可能会使情况变得更糟。
给定样本数据:
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 行进行操作,因此它将生成更多的撤消/重做日志,对所有可能的匹配项进行操作,而不仅仅是这些行的所需子集。