在Oracle中使用select子句中的连接速度慢吗?

时间:2010-05-22 02:38:32

标签: performance oracle

我想写一个类似下面的查询

select 
  username, 
  (select state from addresses where addresses.username = users.username) email
from users

这适用于Oracle(假设内部查询的结果是唯一的)。但是,这种写作查询方式是否存在性能损失?

2 个答案:

答案 0 :(得分:1)

这不是join本身,而是子查询与主select语句的串联。

为了使它成为连接(速度更快),您需要以下语法:

select users.username as username, addresses.state as email from users
left join state on (users.username = addresses.username)

select语句中使用子查询总是会在DBMS中受到惩罚。将每个子查询视为一个单独的临时表,仅在查询期间存在于内存中,之后DBMS会将其销毁。首先,它为主select分配内存,然后为子查询表分配更多内存,完整地执行子查询,然后查看两个表以整理结果集。

此外,临时表没有索引优化,因为它们是派生表,并且DBMS已编程为不花时间生成索引(除非DBMS真的非常非常聪明)。

然而,对于join,内存仅分配给主select结果表,并使用主结果集填充一次,并添加到join ed表时搜索(使用为表格设置的任何索引)。

答案 1 :(得分:1)

回到最初的问题,联接是的数据库。如果他们不能很好地加入,他们就会在市场上失败。因此,您会发现此处讨论的任何变体都会很快。

请注意,“用户”是Oracle中的保留字 - 您可能想要将您的表称为其他内容。另请注意,如果用户的地址中有多条记录,则会在原始公式中引发错误。正常连接只会返回多行。

使用我自己的表格以及合理的索引和数据量,解释计划是:

原始

SELECT STATEMENT  ALL_ROWSCost: 226  Bytes: 390,570  Cardinality: 39,057        
    2 TABLE ACCESS BY INDEX ROWID TABLE X83109.FN_AR_INVOICE Cost: 2  Bytes: 13  Cardinality: 1     
        1 INDEX UNIQUE SCAN INDEX (UNIQUE) X83109.I_FN_AR_INVOICE Cost: 1  Cardinality: 1  
    3 TABLE ACCESS FULL TABLE X83109.FN_AR_LINE_ITEM Cost: 226  Bytes: 390,570  Cardinality: 39,057  

ANSI Join(如上所述)或传统的Oracle语法,如下所示

select users.username as username, addresses.state as email from users, addresses where users.username = addresses.username; 

SELECT STATEMENT  ALL_ROWSCost: 377  Bytes: 898,311  Cardinality: 39,057        
    3 HASH JOIN  Cost: 377  Bytes: 898,311  Cardinality: 39,057     
        1 TABLE ACCESS FULL TABLE X83109.FN_AR_INVOICE Cost: 149  Bytes: 333,788  Cardinality: 25,676  
        2 TABLE ACCESS FULL TABLE X83109.FN_AR_LINE_ITEM Cost: 226  Bytes: 390,570  Cardinality: 39,057 

所以没有太大区别。您应该随意使用联接,但也可以监视性能。