![](/img/trans.png)
[英]In Oracle SQL, can I query a partition of a table instead of an entire table to make it run faster?
[英]How can I alter my table to make Oracle merge run faster?
我有一個表,DASHBOARD,主鍵是PERSON_ID。
我想使用MERGE語句為每列填充所有PERSON_ID,該語句向另一個表查詢計數ALERT_EVENTS。
我為每一列編寫了MERGE語句,下面是其中一個查詢 -
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,因此它不是一個包含的功能。
如何在不使用分區的情況下加速此合並語句?
我正在考慮拋棄大部分行,這會有所幫助,但潛在的問題仍然存在。
我在這里錯過了什么?
提前感謝任何想法。
我沒有在Oracle上使用merge,所以不是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);
我還在插入中包含了區域,刪除它以保持與原始查詢一致是微不足道的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.