I have a table, DASHBOARD, with a primary key of PERSON_ID.
I want to populate all PERSON_IDs for each column using a MERGE statement that queries another table for counts, ALERT_EVENTS.
I have written MERGE statements for each column, below is one of the queries -
MERGE INTO DASHBOARD D
USING
(SELECT PERSON_ID FROM PERSON) P
ON (D.PERSON_ID = P.PERSON_ID)
WHEN MATCHED THEN
UPDATE SET D.ZONES = (SELECT COUNT(EVENT_ID) FROM ALERT_EVENTS WHERE PERSON_ID = P.PERSON_ID AND EMAIL_ALERT_TYPE_ID = '40') WHERE D.PERSON_ID = P.PERSON_ID
WHEN NOT MATCHED THEN
INSERT (D.PERSON_ID)
VALUES (P.PERSON_ID);
My problem is this query takes too long to run, usually around 50 minutes.
There are 4000 PERSON_IDs in the DASHBOARD table and there are 1.4 million EVENT_IDs in the ALERT_EVENTS table.
The ALERT_EVENTS table is made up of the following columns -
"EVENT_ID" NUMBER(*,0) NOT NULL ENABLE,
"PERSON_ID" NUMBER(*,0) NOT NULL ENABLE,
"DEVICE_ID" NUMBER(*,0) NOT NULL ENABLE,
"ALERT_TYPE_ID" NUMBER(*,0) NOT NULL ENABLE,
"EVENT_DATE_TIME" DATE NOT NULL ENABLE,
"TEXT" VARCHAR2(4000 BYTE),
"STATUS" NUMBER(*,0) DEFAULT 0 NOT NULL ENABLE,
"PROC_STATUS_ID" NUMBER(*,0) DEFAULT 1 NOT NULL ENABLE,
"ALERT_STATUS_ID" NUMBER DEFAULT 1 NOT NULL ENABLE
and one UNIQUE index on EVENT_ID.
I have tried adding and removing indexes (tried with 1 index and 3 indexes), which doesn't seem to help performance.
Based on my EXPLAIN PLAN (below), I believe I have a table structure problem, as my database always wants to do a FULL TABLE SCAN when executing the MERGE statement.
Operation Name Rows Bytes Cost (%CPU) Time
MERGE STATEMENT 4127 314K 21 (5) 00:00:01
MERGE DASHBOARD
VIEW
HASH JOIN OUTER 4127 120K 21 (5) 00:00:01
INDEX FAST FULL SCAN PK_PERSON 4127 16508 4 (0) 00:00:01
TABLE ACCESS FULL DASHBOARD 4215 107K 16 (0) 00:00:01
SORT AGGREGATE 1 7
TABLE ACCESS FULL ALERT_EVENTS 27 189 5247 (2) 00:01:03
I was going to partition the table, but we only have Oracle Standard, and not Enterprise, so it's not an included feature.
How can I speed up this merge statement without using partitions?
I am considering throwing out most of the rows, which would help slightly, but the underlying problem still exists.
What am I missing here?
Thanks in advance for any ideas.