[英]How to avoid same subquery in multiple select in oracle?
這是使用相同子查詢的三個不同選擇。 如何使用子查詢結果而不是再次執行子查詢。
SELECT *
FROM Address
WHERE address_key IN
(
SELECT address_key
FROM person_address
WHERE peson_key IN (person_list)
); -- person_list := '1,2,3,4'
SELECT *
FROM Phone
WHERE phone_key IN
(
SELECT address_key
FROM person_address
WHERE peson_key IN (person_list)
);
SELECT *
FROM Email
WHERE address_key IN
(
SELECT address_key
FROM person_address
WHERE peson_key IN (person_list)
);
您可以為此查詢創建物化視圖:
CREATE MATERIALIZED VIEW v_address
REFRESH FORCE ON COMMIT
AS
SELECT address_key
FROM person_address
WHERE person_key IN (person_list)
,或創建一個臨時表並填充它:
CREATE GLOBAL TEMPORARY TABLE tt_address (VARCHAR2(50));
INSERT
INTO tt_address
SELECT address_key
FROM person_address
WHERE person_key IN (person_list)
但是,實際上,如果您為person_key
編制索引,則可以重用子查詢。
由於您有3
單獨的查詢,因此您需要以這樣或那樣的方式顯示您的值。
這意味着您需要將這些值存儲在某處,無論是內存,臨時表空間還是永久表空間。
但是你需要的值已經存儲在person_address
,你只需要獲取它們。
使用子查詢3
次將涉及12
次索引掃描以從person_key
上的索引獲取ROWID
和12
表ROWID
查找以從表中獲取address_key
。 然后很可能會在它們上構建一個HASH TABLE
。
這是微秒的問題。
當然,臨時表或物化視圖會更高效,但是將子查詢時間從100
微秒更改為50
幾乎不值得,只要主查詢可能需要幾分鍾。
使用with子句。 我沒有重新創建您的確切示例問題,但可以在WITH子句中放入任意數量的重復子查詢,然后在查詢中引用。
WITH address_keys as (
SELECT address_key
FROM person_address
WHERE peson_key IN (person_list)
)
Select * from table1, table2, address_keys
where table1.address_key = address_keys.address_key
and table2.address_key = address_keys.address_key
首先,我認為在大多數情況下,此優化不會帶來顯着的改進(在第一次查詢之后,PERSON_ADDRESS的數據塊將主要緩存在緩沖區緩存中,因此無法從HDD讀取)。
但是作為案例研究或出於任何原因:您需要緩存重復的查詢結果,然后在3個選擇中重復使用它們。 這可以通過(temp)表或MV或plsql結構varray來實現。
前兩個選項在他的回答中涵蓋了Quassnoi,所以我不會提及它們。 第三個缺點是必須事先聲明最大行數(我不知道當你聲明一個上限為1M或1G項目的varray時會發生什么,即使你只需要1k)。
--creating db object to hold the data - maximum of 1000 items allowed.
--I assume that key is number(10,0).
create type t_address_keys is varray (1000) of number (10,0);
declare
la_address_keys t_address_keys; --declare cache variable
begin
--cache keys
SELECT address_key
bulk collect into la_address_keys
FROM person_address
WHERE peson_key IN (person_list);
SELECT *
into ...
FROM Address
WHERE address_key IN table(la_address_keys);
SELECT *
into ...
FROM Phone
WHERE address_key IN table(la_address_keys);
SELECT *
into ...
FROM email
WHERE address_key IN table(la_address_keys);
end;
/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.