Oracle Optimization - 更新和子查询

时间:2017-07-26 19:53:47

标签: oracle

我有两个非常大的表(一个记录超过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'

我在这里做错了什么?

谢谢

2 个答案:

答案 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上有索引,假设只有一小部分行属于最后一天或者如此。