【问题标题】:SQL Join between tables with conditions带条件的表之间的 SQL 连接
【发布时间】:2014-01-26 20:00:16
【问题描述】:

我正在考虑在某些条件下在 2 个或多个表之间进行联接的最佳方式(考虑到执行时间)。我得到了这三种方法:

第一种方式:

select * from 
TABLE A inner join TABLE B on A.KEY = B.KEY
where 
B.PARAM=VALUE

第二种方式

select * from 
TABLE A inner join TABLE B on A.KEY = B.KEY 
and B.PARAM=VALUE

第三种方式

select * from
TABLE A inner join (Select * from TABLE B where B.PARAM=VALUE) J ON A.KEY=J.KEY

假设表有超过 100 万行。

你有什么意见?如果存在,哪个应该是正确的方式?

【问题讨论】:

  • Oracle 查询优化器将所有这些都视为相同,性能差异应该不大。你检查结果了吗?
  • 要回答有关性能的问题,您需要查看执行计划(或在类似情况下为查询计时)。 Oracle 有一个很好的优化器,所以我的猜测是所有三个查询都将具有相同的计划和相同的性能。
  • 发布与性能相关的问题时,最好阅读以下内容:tkyte.blogspot.com/2005/06/how-to-ask-questions.html
  • 您真的只考虑内部连接,还是只是为了保持示例较小?如果您必须处理外部连接,事情会变得更加复杂。

标签: sql oracle join


【解决方案1】:

通常将条件放在 where 子句或连接条件中,在内连接中没有明显差异。
如果您使用外连接,将条件放在 where 子句中会缩短查询时间,因为当您在 where 子句中使用条件时 左外连接,不满足条件的行将从结果集中删除,结果集变小。 但是如果在左外连接的连接子句中使用条件,则与在 where 子句中使用条件相比,不会删除任何行并且结果集更大。 如需更多说明,请按照示例进行操作。

创建表A

( 没有数字,

名称 VARCHAR2(10),

日期日期 )

----一个数据

插入 A 从对偶中选择 1,'Amand',to_date('20130101','yyyymmdd'); 提交;

插入 A select 2,'Alex',to_date('20130101','yyyymmdd') from dual; 提交;

插入 A select 3,'Angel',to_date('20130201','yyyymmdd') from dual;

提交;

创建表B

( bno NUMBER,

bname VARCHAR2(10),

日期日期 )

插入 B 从对偶中选择 3,'BOB',to_date('20130201','yyyymmdd'); 提交;

插入 B 从对偶中选择 2,'Br',to_date('20130101','yyyymmdd'); 提交;

插入 B select 1,'Bn',to_date('20130101','yyyymmdd') from dual; 提交;

首先,我们有正常的查询,它将 2 个表相互连接:

select * from a inner join b on a.ano=b.bno

结果集有 3 条记录。 现在请运行以下查询:

select * from a inner join b on a.ano=b.bno and a.rdate=to_date('20130101','yyyymmdd')

    select * from a inner join b on a.ano=b.bno where a.rdate=to_date('20130101','yyyymmdd')

正如您在上面看到的结果,行数没有差异,根据我的经验,大容量数据没有明显的性能差异。

请运行以下查询:

select * from a left outer  join b on a.ano=b.bno and a.rdate=to_date('20130101','yyyymmdd')

在这种情况下,输出记录的数量将等于表 A 的记录。

select * from a left outer  join b on a.ano=b.bno where a.rdate=to_date('20130101','yyyymmdd')

在这种情况下,不满足条件的 A 记录从结果集中删除,正如我所说,结果集中的记录将更少(在这种情况下为 2 条记录)。

根据以上例子我们可以得出以下结论:

1-在使用内部连接的情况下, 将条件放在 where 子句或 join 子句中没有特别的区别,但请尝试将表放在 from 子句中,以使中间结果行数最少: (http://www.dba-oracle.com/art_dbazine_oracle10g_dynamic_sampling_hint.htm)

2-在使用外连接的情况下,只要您不关心确切的结果行数(不关心表 A 的缺失记录,表 B 中没有配对记录,表 B 的字段将为空对于结果集中的这些记录),将条件放在where子句中以删除一组不满足条件的行,并通过减少结果行数来明显提高查询时间。

但在特殊情况下,您必须将条件放在连接部分中。例如,如果您希望结果行数等于表“A”行数(这种情况在 ETL 流程中很常见),您必须将条件放在连接子句中。

3-避免子查询被很多可靠的资源和专家程序员推荐。它通常会增加查询时间,你可以在结果数据集很小的时候使用子查询。

我希望这会很有用:)

【讨论】:

    【解决方案2】:

    1M 行确实不是 那么 - 特别是如果您有合理的索引。我会从使您的查询尽可能可读和可维护开始,并且只有在您发现查询的性能问题时才开始优化(正如 Gordon Linoff 在他的评论中所说的那样——这三者之间甚至会有差异是值得怀疑的)。

    这可能是一个品味问题,但对我来说,第三种方式似乎很笨拙,所以我将它划掉。就个人而言,我更喜欢将JOIN 语法用于连接逻辑(即A 和B 的行如何匹配)和WHERE 用于过滤(即一旦匹配,哪些行让我感兴趣),所以我会选择第一个方法。但同样,这真的归结为个人品味和偏好。

    【讨论】:

      【解决方案3】:

      您需要查看查询的执行计划,以判断哪个计算效率最高。正如 cmets 中所指出的,您可能会发现它们是等价的。以下是有关Oracle execution plans 的一些信息。根据您使用的编辑器/IDE,这可能是一个快捷方式,例如在 PL/SQL Developer 中按 F5。

      【讨论】:

        猜你喜欢
        • 2013-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多