我有两个非常大的表(一个记录超过500 M,另一个记录超过1B)
如果表2中的一个字段连续包含4个以上的Char(10)个字符,我需要更新表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'
我在这里做错了什么?
谢谢
答案 0 :(得分:1)
嗯。使用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”)
答案 1 :(得分:1)
你做错了是你不必要地加入第一个表两次:一次在子查询中(已经在MERGE
中完成了工作),再次在ON
子句MERGE
子句中1}}。
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
上有索引,假设只有一小部分行属于最后一天或者如此。