我有两个非常大的表(一个有超过 500 M 条记录,另一个有超过 1B 条记录(
如果表二中的一个字段连续包含超过 4 个字符,我需要更新表 1 中记录的状态。
当我查找符合该标准的记录时,大约需要 10 分钟 -
SELECT B.ID as main_id
FROM Table A, TABLE B
WHERE A.CREATED_DATE > TRUNC(SYSDATE -1)
AND A.STATUS_CODE = 'IN PROGRESS'
AND A.ID = B.ID
AND (REGEXP_COUNT(B.TEXT, CHR(10) || '{4},1,'mn')) > 0
现在,我需要查找表 A 中的所有记录,并根据上面的查询将状态字段更新为 FAIL。 基本上,我在上面起诉作为更新的子查询。 但是,当我这样做时,我的更新语句运行了很长时间,我希望它运行的时间略长于 10 分钟(上面的查询只返回 2 条记录(。 这是我所拥有的-->
MERGE INTO TABLE A
USING (SELECT B.ID as main_id
FROM Table A, TABLE B
WHERE A.CREATED_DATE > TRUNC(SYSDATE -1)
AND A.STATUS_CODE = 'IN PROGRESS'
AND A.ID = B.ID
AND (REGEXP_COUNT(B.TEXT, CHR(10) || '{4},1,'mn')) > 0) CHECK_ERRORS
ON (A.ID = CHECK_ERRORS.main_id)
WHEN MATCHED THEN UPDATE SET A.STATUS_CODE = 'FAILED'
我在这里做错了什么?
谢谢
你做错了什么,你不必要地连接了第一个表两次:一次在子查询中(它已经完成了MERGE
中所需的工作(,另一次在MERGE
的ON
子句中。
MERGE
语句应该是这样的:
merge into table_a a
using table_b b
on ( a.id = b.id )
when matched then update
set a.status_code = 'FAILED'
where a.created_date > trunc(sysdate - 1)
and a.status_code = 'IN PROGRESS'
and b.text like '%' || chr(10) || chr(10) || chr(10) || chr(10) || '%'
;
如果您在两个表中的id
列上都有索引,并且假设只有一小部分行落在最后一天左右,这也将有助于加快处理速度,也许还有created_date
。
嗯,使用B.TEXT LIKE '%'||CHR(10)||CHR(10)||CHR(10)||CHR(10)||'%'
而不是REGEXP_COUNT
不是更快吗?
诚然,我不经常使用 MERGE,但如果你只是在做更新,我会这样写第二条语句:
UPDATE A
SET A.STATUS_CODE = 'FAILED'
WHERE A.CREATED_DATE > TRUNC(SYSDATE -1)
AND A.STATUS_CODE = 'IN PROGRESS'
AND A.ID IN (SELECT B.ID FROM B WHERE B.TEXT LIKE
'%'||CHR(10)||CHR(10)||CHR(10)||CHR(10)||'%');
(我根据您的代码假设您的意思是表 2 字段包含 4+ CHR10 个字符,而不是"超过 4 个"(