0

PERSON_ID の主キーを持つテーブル DASHBOARD があります。
別のテーブル ALERT_EVENTS にクエリを実行する MERGE ステートメントを使用して、各列のすべての PERSON_ID を入力したいと考えています。

各列のMERGEステートメントを作成しました。以下はクエリの1つです-

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);

私の問題は、このクエリの実行に時間がかかりすぎることです。通常は約 50 分です。

DASHBOARD テーブルには 4000 個の PERSON_ID があり、ALERT_EVENTS テーブルには 140 万個の EVENT_ID があります。ALERT_EVENTS テーブルは、次の列で構成されています -

"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.

インデックスの追加と削除を試みましたが (1 つのインデックスと 3 つのインデックスで試しました)、パフォーマンスが向上しないようです。

EXPLAIN PLAN (下記) に基づいて、データベースは MERGE ステートメントを実行するときに常に FULL TABLE SCAN を実行する必要があるため、テーブル構造に問題があると思います。

 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

テーブルを分割するつもりでしたが、Oracle Standard しかなく、Enterprise がないため、含まれていません。

パーティションを使用せずにこのマージ ステートメントを高速化するにはどうすればよいですか?

ほとんどの行を破棄することを検討していますが、これはわずかに役立ちますが、根本的な問題はまだ存在しています。

ここで何が欠けていますか?

アイデアをお寄せいただきありがとうございます。

4

1 に答える 1

2

私は Oracle でマージを使用していないため、これが機能することを 100% 確信しているわけではありませんが、特にalert_events (email_alert_type_id, person_id)またはのインデックスを使用すると、次の処理が高速になるはずalert_events (person_id, email_alert_type_id)です。理想的には、最初のものを使用して、クエリ プランでマージ結合を確認しますが、Oracle のクエリ オプティマイザがこれを実行できるかどうかはわかりません。

merge into 
    dashboard d
using (
    select
        p.person_id,
        count(e.person_id) zones
    from
        person p
            left outer join
        alert_events e
            on p.person_id = e.person_id and 
               e.email_alert_type_id = '40' 
    group by
        p.person_id
    ) x
on
    (d.person_id = x.person_id)
when matched then update
    set d.zones = x.zones
when not matched then insert (person_id, zones)
    values (x.person_id, x.zones);

挿入にゾーンも含めました。これを削除して、元のクエリと一致させるのは簡単です。

于 2013-11-09T02:22:04.057 に答える