Reputation: 11
I have two very large tables (one with over 500 M records and the other with over 1B records)
I need to update status of the record in table one if one of the fields in table two contains more than 4 Char(10) characters in a row.
When I look for the records that meet that criteria it takes approximately 10 min -
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
Now, I need to look up all of the records in table A and update status field to FAIL based on the query above. Basically I am suing above as a sub-query for the update. However, when I do that, my update statements run for a very long time where I would expect it to run slightly longer than 10 minutes (above query returns only 2 records back). Here is what I have -->
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'
What am I doing wrong here?
Thank you
Upvotes: 1
Views: 147
Reputation:
What you are doing wrong is that you are unnecessarily joining the first table twice: once in the subquery (which already does the work needed in MERGE
) and again in the ON
clause of MERGE
.
The MERGE
statement should be something like this:
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) || '%'
;
It will also help speed up the processing if you had indexes on the id
columns in both tables, and perhaps also on created_date
, assuming only a small fraction of rows fall within the last day or so.
Upvotes: 1
Reputation: 9091
Hmm. Wouldn't it be faster to use B.TEXT LIKE '%'||CHR(10)||CHR(10)||CHR(10)||CHR(10)||'%'
instead of REGEXP_COUNT
?
Admittedly, I don't use MERGE very often, but if you're just doing updates, I would write the second statement like this:
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)||'%');
(I'm assuming based on your code that you meant the Table 2 field contains 4+ CHR10 characters, not "more than 4")
Upvotes: 0