查询优化 Not in to Left outer join
Posted
技术标签:
【中文标题】查询优化 Not in to Left outer join【英文标题】:Query optimization Not in to Left outer join 【发布时间】:2011-05-28 16:55:36 【问题描述】:考虑下表;
测试
SQL> desc test;
Name Null? Type
----------------------------------------- -------- ----------------------------
NUM NOT NULL NUMBER
NUM2 NUMBER(10)
NUM3 NUMBER
NUM NUM2 NUM3
---------- ---------- ----------
1 1 1
2 2 2
测试2
SQL> desc test2;
Name Null? Type
----------------------------------------- -------- ----------------------------
NUM NOT NULL NUMBER
NUM2 NOT NULL NUMBER
NUM3 NUMBER
NUM NUM2 NUM3
---------- ---------- ----------
1 1 1
3 1 1
根据本书,如果要将 NOT IN 条件替换为 LEFT Outer join ;查询性能会提高。
解释计划 1
SQL> select *
from test
where num NOT IN (select num
from test2);
NUM NUM2 NUM3
--- --------- ----------
2 2 2
执行计划
----------------------------------------------------------
Plan hash value: 856752680
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 5 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| TEST | 2 | 4 | 3 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| TEST2 | 2 | 26 | 2 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( NOT EXISTS (SELECT /*+ */ 0 FROM "TEST2" "TEST2" WHERE
LNNVL("NUM"<>:B1)))
3 - filter(LNNVL("NUM"<>:B1))
所以我在两个表的 num 列上创建了索引,并将查询重写为:
解释计划 2
SQL> select *
from test
left join test2 on (test.num = test2.num)
where test2.num is null;
NUM NUM2 NUM3 NUM NUM2 NUM3
---------- ---------- ---------- ---------- ---------- ----------
2 2 2
Execution Plan
----------------------------------------------------------
Plan hash value: 1525288557
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Tim
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 82 | 4 (0)| 00:
|* 1 | FILTER | | | | |
| 2 | NESTED LOOPS OUTER | | 2 | 82 | 4 (0)| 00:
| 3 | TABLE ACCESS FULL | TEST | 2 | 4 | 3 (0)| 00:
| 4 | TABLE ACCESS BY INDEX ROWID| TEST2 | 1 | 39 | 1 (0)| 00:
|* 5 | INDEX RANGE SCAN | ID2 | 1 | | 0 (0)| 00:
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("TEST2"."NUM" IS NULL)
5 - access("TEST"."NUM"="TEST2"."NUM"(+))
我显然遗漏了一些东西,因为建议的方法被证明更昂贵。这是因为我的数据分布吗?
版本:Oracle 10g
【问题讨论】:
您已发布数据,但未发布表格信息。由于存在差异,我倾向于认为被比较的列可以为空due to the info in this article Oracle 10g ,也有问题更新:) 您的两个查询返回不同的结果集。第二个版本也从第二个表返回数据。我希望从两个表返回数据的查询比只从一个表返回数据的查询更昂贵。尝试使用select test.*
而不是 select *
进行第二个查询,看看它是否有所作为。
@APC 是的!这就是原因,您能否将其作为答案发布,以便我接受?干杯!
【参考方案1】:
您的两个查询返回不同的结果集。第二个版本也从第二个表返回数据。我希望从两个表返回数据的查询比只从一个表返回数据的查询更昂贵。
尝试使用select test.*
而不是select *
进行第二个查询,看看它是否有所作为。
【讨论】:
以上是关于查询优化 Not in to Left outer join的主要内容,如果未能解决你的问题,请参考以下文章
LEFT OUTER JOIN 和 NOT EXISTS 查询
关于left join优化not in 导致的长时间查询无数据问题 Using where; Using join buffer (Block Nested Loop)
Sql语句优化-查询两表不同行NOT INNOT EXISTS连接查询Left Join
努力优化 Rails WHERE NOT IN 在 Rails 中的查询