Performance 在Oracle中,在select子句中使用联接是否很慢?
我想写一个如下的查询Performance 在Oracle中,在select子句中使用联接是否很慢?,performance,oracle,Performance,Oracle,我想写一个如下的查询 select username, (select state from addresses where addresses.username = users.username) email from users 假设内部查询的结果是唯一的,则这在Oracle中有效。但是,这种编写查询的方式会带来性能损失吗?这不是连接本身,而是子查询与主select语句的连接 为了使其成为更快的联接,您需要以下语法: select users.username as usern
select
username,
(select state from addresses where addresses.username = users.username) email
from users
假设内部查询的结果是唯一的,则这在Oracle中有效。但是,这种编写查询的方式会带来性能损失吗?这不是连接本身,而是子查询与主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非常非常聪明
然而,使用联接时,内存仅分配给主选择结果表,并使用主结果集填充一次,并在使用为该表设置的任何索引搜索联接表时添加到内存中。回到原始问题,联接是数据库所做的事。如果他们做得不好,他们就会在市场上惨败。所以你会发现这里讨论的任何一种变化都会很快 请注意,在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
所以没有太大区别。您应该可以随意使用联接,但也可以监视性能 我称之为相关子查询。有趣的是,它位于from子句中,因此可能会得到另一个特殊的名称?它在Oracle中称为标量子查询。执行整个子查询,然后查看两个表以整理结果集。这是不正确的。Oracle将在主结果集中获得一行,然后使用用户名访问addresses表。如果用户名列以地址为索引,则将使用该索引。