簡體   English   中英

如何在oracle的多個select中避免使用相同的子查詢?

[英]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上的索引獲取ROWID12ROWID查找以從表中獲取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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM