如何让oracle建立索引语句 In 语句走索引

后使用快捷导航没有帐号?
查看: 1166|回复: 9
查询语句中exists和in子句不走索引的不解
高级会员, 积分 536, 距离下一级还需 464 积分
论坛徽章:2
有以下一个简单例子:
t1(共1000行,属于小表):
SQL& SELECT * FROM T1 where rownum&10;
& && &&&ID NAME
---------- --------
& && && &1 boobooke
& && && &2 boobooke
& && && &3 boobooke
& && && &4 boobooke
& && && &5 boobooke
& && && &6 boobooke
& && && &7 boobooke
& && && &8 boobooke
& && && &9 boobooke
9 rows selected
t2:(共1百万行,为了让其占用较大的数据块,增大后面两列的数据,使其跟索引的大小拉大)
SQL& SELECT * FROM T2 where rownum&10;
& && &&&ID NAME& &&&A& && && && && && && && && && && && && && && && && && && && && && && && && &&&B
---------- -------- ----------------------------------------------------------------------------- --------------------------------------------------
& && && &1 boobooke aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
& && && &2 boobooke aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
& && && &3 boobooke aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
& && &1004 boobooke aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
& && &1005 boobooke aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
& && &1006 boobooke aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
& && &1007 boobooke aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
& && &1008 boobooke aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
& && &1009 boobooke aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
其中ID在t1和t2中均是主键,并且ID为1,2,3的为其交集,如果用普通的查询语句连接是会走索引的:
普通连接:
SQL& set autotrace on
SQL& select t1.* from t1,t2 where t2.id=t1.
& && &&&ID NAME
---------- --------
& && && &1 boobooke
& && && &2 boobooke
& && && &3 boobooke
----------------------------------------------------------
Plan hash value:
--------------------------------------------------------------------------------
| Id&&| Operation& && && && & | Name& &&&| Rows&&| Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& && &|& && && & |&&1000 | 25000 |& & 36& &(9)| 00:00:01
|*&&1 |&&HASH JOIN& && && && &|& && && & |&&1000 | 25000 |& & 36& &(9)| 00:00:01
|& &2 |& &TABLE ACCESS FULL& &| T1& && & |&&1000 | 12000 |& &&&7& &(0)| 00:00:01
|& &3 |& &INDEX FAST FULL SCAN| IX_T2_ID | 54958 |& &697K|& & 27& &(4)| 00:00:01
--------------------------------------------------------------------------------
但问题如果用exists或用in子句来代替,执行计划就选择了全表扫描:
SQL& select * from t1 where&&exists (select 1 from t2 where t2.id=t1.id);
& && &&&ID NAME
---------- --------
& && && &1 boobooke
& && && &2 boobooke
& && && &3 boobooke
----------------------------------------------------------
Plan hash value:
-------------------------------------------------------------------------------
| Id&&| Operation& && && &&&| Name& & | Rows&&| Bytes | Cost (%CPU)| Time& &&&|
-------------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& & |& && && &|&&1000 | 25000 |& &240& &(2)| 00:00:03 |
|*&&1 |&&HASH JOIN SEMI& &&&|& && && &|&&1000 | 25000 |& &240& &(2)| 00:00:03 |
|& &2 |& &TABLE ACCESS FULL | T1& && &|&&1000 | 12000 |& &&&7& &(0)| 00:00:01 |
|& &3 |& &VIEW& && && && &&&| VW_SQ_1 | 54958 |& &697K|& &232& &(2)| 00:00:03 |
|& &4 |& & TABLE ACCESS FULL| T2& && &| 54958 |& &697K|& &232& &(2)| 00:00:03 |
-------------------------------------------------------------------------------
SQL& select * from t1 where t1.id in (select id from t2 where t2.id=t1.id);
& && &&&ID NAME
---------- --------
& && && &1 boobooke
& && && &2 boobooke
& && && &3 boobooke
----------------------------------------------------------
Plan hash value:
-------------------------------------------------------------------------------
| Id&&| Operation& && && &&&| Name& & | Rows&&| Bytes | Cost (%CPU)| Time& &&&|
-------------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& & |& && && &|& &&&1 |& & 38 |& &240& &(2)| 00:00:03 |
|*&&1 |&&HASH JOIN SEMI& &&&|& && && &|& &&&1 |& & 38 |& &240& &(2)| 00:00:03 |
|& &2 |& &TABLE ACCESS FULL | T1& && &|&&1000 | 12000 |& &&&7& &(0)| 00:00:01 |
|& &3 |& &VIEW& && && && &&&| VW_SQ_1 | 50116 |&&1272K|& &232& &(2)| 00:00:03 |
|& &4 |& & TABLE ACCESS FULL| T2& && &| 50116 |& &244K|& &232& &(2)| 00:00:03 |
-------------------------------------------------------------------------------
网上的查过
in操作的原理是先进性子查询操作,再进行主查询操作(适合主查询是大表,子查询是小表)。
exists操作的原理是先进行主查询操作,再到子查询中进行过滤(适合主查询是小表,子查询是大表)。
exists好像会有可能导致错误的执行计划,不知什么原理?
请大家帮忙分析一下什么原因造成IN和EXISTS不走索引?
论坛徽章:8
sys@MAA& select * from v$version where rownum &= 1;
BANNER
----------------------------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
luocs@MAA& show user
USER is &LUOCS&
luocs@MAA& select * from t1;
& && &&&ID NAME& && && && && && && && && &LOGINDATE
---------- ------------------------------ -----------------------
& && && &1 LTB& && && && && && && && && & 17-OCT-:54
& && && &2 LUOCS& && && && && && && && &&&17-OCT-:54
& && && &3 LTB& && && && && && && && && & 17-OCT-:54
& && && &4 LUOCS& && && && && && && && &&&17-OCT-:54
luocs@MAA& select * from t2;
& && &&&ID ADDRESS
---------- ------------------------------------------------------------
& && && &1 CHANGPING
& && && &2 HAIDIAN
& && && &3 CHANGPING
& && && &4 HAIDIAN
luocs@MAA& col INDEX_NAME for a15
luocs@MAA& col INDEX_TYPE for a15
luocs@MAA& col TABLE_NAME for a15
luocs@MAA& select INDEX_NAME, INDEX_TYPE, TABLE_NAME from user_
INDEX_NAME& && &INDEX_TYPE& && &TABLE_NAME
--------------- --------------- ---------------
INX_ID_T2& && & NORMAL& && && & T2
INX_T1& && && & NORMAL& && && & T1
luocs@MAA& set autot traceonly exp
luocs@MAA& select * from t1, t2 where t1.id = t2.
Execution Plan
----------------------------------------------------------
Plan hash value:
------------------------------------------------------------------------------------------
| Id&&| Operation& && && && && && &&&| Name& && &| Rows&&| Bytes | Cost (%CPU)| Time& &&&|
------------------------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& && && && & |& && && &&&|& &&&4 |& &112 |& &&&6&&(17)| 00:00:01 |
|& &1 |&&MERGE JOIN& && && && && && &|& && && &&&|& &&&4 |& &112 |& &&&6&&(17)| 00:00:01 |
|& &2 |& &TABLE ACCESS BY INDEX ROWID| T2& && &&&|& &&&4 |& & 48 |& &&&2& &(0)| 00:00:01 |
|& &3 |& & INDEX FULL SCAN& && && &&&| INX_ID_T2 |& &&&4 |& && & |& &&&1& &(0)| 00:00:01 |
|*&&4 |& &SORT JOIN& && && && && && &|& && && &&&|& &&&4 |& & 64 |& &&&4&&(25)| 00:00:01 |
|& &5 |& & TABLE ACCESS FULL& && && &| T1& && &&&|& &&&4 |& & 64 |& &&&3& &(0)| 00:00:01 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
& &4 - access(&T1&.&ID&=&T2&.&ID&)
& && & filter(&T1&.&ID&=&T2&.&ID&)
luocs@MAA& select * from t1 where exists (select 1 from t2 where t1.id = t2.id);
Execution Plan
----------------------------------------------------------
Plan hash value:
--------------------------------------------------------------------------------
| Id&&| Operation& && && & | Name& && &| Rows&&| Bytes | Cost (%CPU)| Time& &&&|
--------------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& &|& && && &&&|& &&&4 |& & 76 |& &&&3& &(0)| 00:00:01 |
|& &1 |&&NESTED LOOPS SEMI |& && && &&&|& &&&4 |& & 76 |& &&&3& &(0)| 00:00:01 |
|& &2 |& &TABLE ACCESS FULL| T1& && &&&|& &&&4 |& & 64 |& &&&3& &(0)| 00:00:01 |
|*&&3 |& &INDEX RANGE SCAN | INX_ID_T2 |& &&&4 |& & 12 |& &&&0& &(0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
& &3 - access(&T1&.&ID&=&T2&.&ID&)
luocs@MAA& select * from t1 where t1.id in (select id from t2 where t1.id=t2.id);
Execution Plan
----------------------------------------------------------
Plan hash value:
--------------------------------------------------------------------------------
| Id&&| Operation& && && & | Name& && &| Rows&&| Bytes | Cost (%CPU)| Time& &&&|
--------------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& &|& && && &&&|& &&&4 |& & 76 |& &&&3& &(0)| 00:00:01 |
|& &1 |&&NESTED LOOPS SEMI |& && && &&&|& &&&4 |& & 76 |& &&&3& &(0)| 00:00:01 |
|& &2 |& &TABLE ACCESS FULL| T1& && &&&|& &&&4 |& & 64 |& &&&3& &(0)| 00:00:01 |
|*&&3 |& &INDEX RANGE SCAN | INX_ID_T2 |& &&&4 |& & 12 |& &&&0& &(0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
& &3 - access(&T1&.&ID&=&ID&)
复制代码
高级会员, 积分 536, 距离下一级还需 464 积分
论坛徽章:2
楼上的,你的测试结果为何跟我的不一样?你觉得原因在于?表统计信息分析我是已经做过的
论坛徽章:1
看SQL的执行计划,不是比较执行计划是否一样,而要看执行计划是否是最优的,如果Oracle选择了一个很差的执行计划,这个可以作为讨论的话题,至于为什么一会这个,一会那个,那是CBO计算的结果。
同样的SQL,不同的数据,很可能执行计划不同,这很正常啊。
论坛徽章:17
看SQL的执行计划,不是比较执行计划是否一样,而要看执行计划是否是最优的,如果Oracle选择了一个很差的执行 ...[/quote]
我想楼主的意思,是原本预计的查询会走索引,但是结果没有。
楼主应该是想整明白CBO的选择是否是正确的。
对于数据量很小的表,大概就能预测到什么样的查询走什么样的执行计划是最优的。
但是对于数据量很大的表,怎么快速判断CBO选择的执行计划是最优的?或者说是正确的?
论坛徽章:8
你看你的数据值,重复行多与重复行少等,都会影响执行计划。
比如:大多数为重复行:
luocs@BBK& select t1.id, t1.name from t1, t2 where t1.id = t2.
Execution Plan
----------------------------------------------------------
Plan hash value:
-----------------------------------------------------------------------------------
| Id&&| Operation& && && && & | Name& && &| Rows&&| Bytes | Cost (%CPU)| Time& &&&|
-----------------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& && &|& && && &&&|& &888M|& &&&9G|&&1025& &(1)| 00:00:13 |
|& &1 |&&NESTED LOOPS& && && &|& && && &&&|& &888M|& &&&9G|&&1025& &(1)| 00:00:13 |
|& &2 |& &INDEX FAST FULL SCAN| INX_T1& & |&&1000 |&&8000 |& &&&3& &(0)| 00:00:01 |
|*&&3 |& &INDEX RANGE SCAN& & | INX_ID_T2 |& &888K|&&3472K|& &&&2& &(0)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
& &3 - access(&T1&.&ID&=&T2&.&ID&)
大多数为不重复行:
luocs@BBK& select t1.id, t1.name from t1, t2 where t1.id = t2.
Execution Plan
----------------------------------------------------------
Plan hash value:
-----------------------------------------------------------------------------------
| Id&&| Operation& && && && & | Name& && &| Rows&&| Bytes | Cost (%CPU)| Time& &&&|
-----------------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& && &|& && && &&&|&&3559K|& & 50M|& &557& &(3)| 00:00:07 |
|*&&1 |&&HASH JOIN& && && && &|& && && &&&|&&3559K|& & 50M|& &557& &(3)| 00:00:07 |
|& &2 |& &INDEX FAST FULL SCAN| INX_T1& & |&&1000 | 11000 |& &&&3& &(0)| 00:00:01 |
|& &3 |& &INDEX FAST FULL SCAN| INX_ID_T2 |&&1000K|&&3906K|& &542& &(1)| 00:00:07 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
& &1 - access(&T1&.&ID&=&T2&.&ID&)
复制代码他们走的执行计划都不一样
高级会员, 积分 536, 距离下一级还需 464 积分
论坛徽章:2
谢谢楼上几位指示,我想应该是因为T1,T2其他字段都有重复值的原因,我改成不重复后T2就走了索引了(T1走全表正常,因为查询结果是要显示T1全部的),至于为什么有重复值,CBO选择了全表,这个还真有点想不通。
---------------------------------------------------------
lan hash value:
------------------------------------------------------------------------------
Id&&| Operation& && && & | Name& &&&| Rows&&| Bytes | Cost (%CPU)| Time& &&&|
------------------------------------------------------------------------------
& &0 | SELECT STATEMENT& &|& && && & |& & 99 |&&7821 |& &&&5& &(0)| 00:00:01 |
*&&1 |&&FILTER& && && && &|& && && & |& && & |& && & |& && && && &|& && && & |
& &2 |& &TABLE ACCESS FULL| T1& && & |& & 99 |&&7821 |& &&&2& &(0)| 00:00:01 |
*&&3 |& &INDEX RANGE SCAN | IX_T2_ID |& &100 |&&1300 |& &&&1& &(0)| 00:00:01 |
------------------------------------------------------------------------------
redicate Information (identified by operation id):
--------------------------------------------------
&&1 - filter( EXISTS (SELECT /*+ */ 0 FROM &T2& &T2& WHERE
& && && && & &T2&.&ID&=:B1))
&&3 - access(&T2&.&ID&=:B1)
高级会员, 积分 536, 距离下一级还需 464 积分
论坛徽章:2
我只要把T1的name字段数据变成重复,执行计划就错误地选择T2全表扫描了(此时T2的name字段是重复的也没问题),消耗成本明显第高于索引访问:
select * from t1 where&&exists (select 1 from t2 where t2.id=t1.id);
----------------------------------------------------------
Plan hash value:
-------------------------------------------------------------------------------
| Id&&| Operation& && && &&&| Name& & | Rows&&| Bytes | Cost (%CPU)| Time& &&&|
-------------------------------------------------------------------------------
|& &0 | SELECT STATEMENT& & |& && && &|& & 99 |&&1980 |& & 13& &(8)| 00:00:01 |
|*&&1 |&&HASH JOIN SEMI& &&&|& && && &|& & 99 |&&1980 |& & 13& &(8)| 00:00:01 |
|& &2 |& &TABLE ACCESS FULL | T1& && &|& & 99 |& &693 |& &&&2& &(0)| 00:00:01 |
|& &3 |& &VIEW& && && && &&&| VW_SQ_1 |&&9999 |& &126K|& & 10& &(0)| 00:00:01 |
|& &4 |& & TABLE ACCESS FULL| T2& && &|&&9999 | 49995 |& & 10& &(0)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
这正是我不解的地方,ORACLE明显是选择了一条错误的代价更高的路吧个人认为。
论坛徽章:1
ftc007 发表于
我只要把T1的name字段数据变成重复,执行计划就错误地选择T2全表扫描了(此时T2的name字段是重复的也没问题 ...
麻烦楼主给出同样数据时,几种执行计划的资源消耗情况。
可以用hint来强制按照你的意志进行数据访问,产生几种不同的执行计划(比如强制走索引)
论坛徽章:8
建议LZ贴代码的时候使用code标签,这样看着方便Oracle中select语句使用索引情况测试_数据库技术_Linux公社-Linux系统门户网站
你好,游客
Oracle中select语句使用索引情况测试
来源:Linux社区&
作者:Linux
--看了不少中sql优化的文章,也介绍了很多不使用索引的情况,今天有空就测试了一下部分情况。 --测试数据 create table EMP ( & EMPNO& VARCHAR2(10) not null primary key, & ENAME& VARCHAR2(10), & JOB&&& VARCHAR2(10), & MGR&&& VARCHAR2(10), & SAL&&& NUMBER(10), & DEPTNO NUMBER(10) )
create index I_DEPTNO on EMP (DEPTNO); create index I_JOB on EMP (JOB); create index I_MGR on EMP (MGR); create index I_SAL on EMP (SAL);
insert into emp values ('01','jacky','clerk','tom','1000','1'); insert into emp values ('02','tom','clerk','','2000','1'); insert into emp values ('03','jenny','sales','pretty','600','2'); insert into emp values ('04','pretty','sales','','800','2'); insert into emp values ('05','buddy','jishu','canndy','1000','3'); insert into emp values ('06','canndy','jishu','','1500','3'); insert into emp values ('07','biddy','clerk','','2000','1'); insert into emp values ('08','biddy','clerk','','2000','3');
--测试及结果: select * from emp where deptno = 1; --使用索引 select * from emp where deptno = '1'; --使用索引(类型转换不影响索引使用)
select * from emp where deptno*2 = 2; --全表扫描(索引列使用函数时不使用索引) select * from emp where deptno = 2/2; --使用索引
select * from emp where ename = 'tom' and deptno = 1; --使用索引 select * from emp where ename = 'tom' or deptno = 1; --全表扫描 (当or条件列都存在索引时会使用索引)
select * from emp where sal != '0'; --全表扫描(!=,null,not null都不使用索引)
select * from emp where mgr = 'tom'; --使用索引(虽然mgr列存在null值还是使用了索引)
select * from emp where deptno in ('1','2','3'); --使用索引(in使用索引)
select * from emp where job like 'c%'; --使用索引(%在第一个字符时不使用索引)
select * from emp where deptno between 1 and 2; --使用索引
--补充一个不使用索引的情况:多列创建索引时,索引第一列不在where中则不使用索引。
相关资讯 & & &
& (02月02日)
& (10/29/:24)
& (06/16/:23)
& (11/14/:10)
& (08/28/:41)
& (05/05/:35)
图片资讯 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款1396人阅读
1. 查询一张表里面索引&
select * from user_indexes where table_name=upper('bills');&
2. 查询被索引字段&
select * from user_ind_columns where index_name=('in_bills');&
3. 给某一字段创建索引&
create index in_bills on bills(account_id);
版权声明:本文为博主原创文章,未经博主允许不得转载。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场sql语句中in与exist&not&in与not&exist&的区别&[oracle]
in和exists
in 是把外表和内表作hash
连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。一直以来认为exists比in效率高的说法是不准确的。
如果查询的两个表大小相当,那么用in和exists差别不大。
in和exists
in 是把外表和内表作hash
连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。一直以来认为exists比in效率高的说法是不准确的。
如果查询的两个表大小相当,那么用in和exists差别不大。
如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:
例如:表A(小表),表B(大表)1:select * from A where cc in (select cc from
效率低,用到了A表上cc列的索引;select * from A where exists(select cc from B
where cc=A.cc)
效率高,用到了B表上cc列的索引。
相反的2:select * from B where cc in (select cc from A)
效率高,用到了B表上cc列的索引;select * from B where exists(select cc from A
where cc=B.cc)
效率低,用到了A表上cc列的索引。
not in 和not exists如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts
的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。
in 与 =的区别
select name from student where name in
('zhang','wang','li','zhao');
select name from student where name='zhang' or name='li' or
name='wang' or name='zhao'
的结果是相同的。
not in 逻辑上不完全等同于not exists,如果你误用了not in,小心你的程序存在致命的BUG:
请看下面的例子:
create table t1 (c1 number,c2 number);
create table t2 (c1 number,c2 number);
insert into t1 values (1,2);
insert into t1 values (1,3);
insert into t2 values (1,2);
insert into t2 values (1,null);
select * from t1 where c2 not in (select c2 from t2);
no rows found
select * from t1 where not exists (select 1 from t2 where
t1.c2=t2.c2);
正如所看到的,not in
出现了不期望的结果集,存在逻辑错误。如果看一下上述两个select语句的执行计划,也会不同。后者使用了hash_aj。
因此,请尽量不要使用not in(它会调用子查询),而尽量使用not
exists(它会调用关联子查询)。如果子查询中返回的任意一条记录含有空值,则查询将不返回任何记录,正如上面例子所示。
除非子查询字段有非空限制,这时可以使用not in ,并且也可以通过提示让它使用hasg_aj或merge_aj连接。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 oracle建索引语句 的文章

 

随机推荐