繁体   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