Oracle 优化 - 更新和子查询



我有两个非常大的表(一个有超过 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中所需的工作(,另一次在MERGEON子句中。

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 个"(