文章标题

scott@ORCL> set autot trace exp;  
scott@ORCL> select * from t1 where id is null;  

Execution Plan  
----------------------------------------------------------  
Plan hash value: 3617692013  

--------------------------------------------------------------------------  
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
--------------------------------------------------------------------------  
|   0 | SELECT STATEMENT  |      |     5 |     5 |     3   (0)| 00:00:01 |  
|*  1 |  TABLE ACCESS FULL| T1   |     5 |     5 |     3   (0)| 00:00:01 |  
--------------------------------------------------------------------------  

Predicate Information (identified by operation id):  
---------------------------------------------------  

   1 - filter("ID" IS NULL)  

-->从上面的测试可知,由于null值是不被存储的,因此当使用id is null作为谓词时,走了全表扫描  

scott@ORCL> select * from t1 where id is not null;  

Execution Plan  
----------------------------------------------------------  
Plan hash value: 796913935  

---------------------------------------------------------------------------------------  
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |  
---------------------------------------------------------------------------------------  
|   0 | SELECT STATEMENT            |         |     1 |     1 |     0   (0)| 00:00:01 |  
|   1 |  TABLE ACCESS BY INDEX ROWID| T1      |     1 |     1 |     0   (0)| 00:00:01 |  
|*  2 |   INDEX FULL SCAN           | I_T1_ID |     1 |       |     0   (0)| 00:00:01 |  
---------------------------------------------------------------------------------------  

Predicate Information (identified by operation id):  
---------------------------------------------------  

   2 - filter("ID" IS NOT NULL)  

-->从上面的测试可知,尽管当前表上id列上的所有值都为null,但不排除后续记录插入的id不为null的列。  
-->故当使用id is not null作为谓词时,此时执行计划中走了索引全扫描。     

-->下面来看看复合索引的情形     
scott@ORCL> select * from t1 where val is null;  

Execution Plan  
----------------------------------------------------------  
Plan hash value: 3617692013  

--------------------------------------------------------------------------  
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
--------------------------------------------------------------------------  
|   0 | SELECT STATEMENT  |      |     2 |     2 |     3   (0)| 00:00:01 |  
|*  1 |  TABLE ACCESS FULL| T1   |     2 |     2 |     3   (0)| 00:00:01 |  
--------------------------------------------------------------------------  

Predicate Information (identified by operation id):  
---------------------------------------------------  

   1 - filter("VAL" IS NULL)  

scott@ORCL> select * from t1 where val is not null;  

Execution Plan  
----------------------------------------------------------  
Plan hash value: 1931510411  

--------------------------------------------------------------------------------  
| Id  | Operation        | Name        | Rows  | Bytes | Cost (%CPU)| Time     |  
--------------------------------------------------------------------------------  
|   0 | SELECT STATEMENT |             |     3 |     3 |     1   (0)| 00:00:01 |  
|*  1 |  INDEX FULL SCAN | I_T1_ID_VAL |     3 |     3 |     1   (0)| 00:00:01 |  
--------------------------------------------------------------------------------  

Predicate Information (identified by operation id):  
---------------------------------------------------  

   1 - filter("VAL" IS NOT NULL)  

-->对于复合唯一索引的情形,当使用单列且非前导列谓词时,使用is null与 is not null等同于单列唯一索引的情形。  
-->即原理也是一样的,val is null走全表扫描而val is not null走索引。因为null值不会被存储。  

-->下面看看两个列都作为谓词的情形     
scott@ORCL> select * from t1 where id is null and val is not null;  

Execution Plan  
----------------------------------------------------------  
Plan hash value: 1040510552  

--------------------------------------------------------------------------------  
| Id  | Operation        | Name        | Rows  | Bytes | Cost (%CPU)| Time     |  
--------------------------------------------------------------------------------  
|   0 | SELECT STATEMENT |             |     3 |     3 |     1   (0)| 00:00:01 |  
|*  1 |  INDEX RANGE SCAN| I_T1_ID_VAL |     3 |     3 |     1   (0)| 00:00:01 |  
--------------------------------------------------------------------------------  

Predicate Information (identified by operation id):  
---------------------------------------------------  

   1 - access("ID" IS NULL)  
       filter("VAL" IS NOT NULL)  

-->从上面的测试可知,尽管两个谓词列上都存在索引,一个为单列唯一索引,一个为复合唯一索引。Oracle 选择了复合索引I_T1_ID_VAL。      

scott@ORCL> select * from t1 where id is not null and val is null;  

Execution Plan  
----------------------------------------------------------  
Plan hash value: 796913935  

---------------------------------------------------------------------------------------  
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |  
---------------------------------------------------------------------------------------  
|   0 | SELECT STATEMENT            |         |     1 |     1 |     0   (0)| 00:00:01 |  
|*  1 |  TABLE ACCESS BY INDEX ROWID| T1      |     1 |     1 |     0   (0)| 00:00:01 |  
|*  2 |   INDEX FULL SCAN           | I_T1_ID |     1 |       |     0   (0)| 00:00:01 |  
---------------------------------------------------------------------------------------  

Predicate Information (identified by operation id):  
---------------------------------------------------  

   1 - filter("VAL" IS NULL)  
   2 - filter("ID" IS NOT NULL)      

-->同样的情形,谓词的顺序与复合索引定义的顺序一样,只不过第一个谓词为id is not null,而第二个谓词为val is null。  
-->此时Oracle 选择了单列唯一索引I_T1_ID  
-->看到此,不知道大家是否已明白,即哪个列为is not null,则会使用该列上的索引,原因还是那句话,索引不存储null值。  
-->对于颠倒id列与val列以及id,val列为null或not null的其他不同组合情形不再演示,其执行计划类似。  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值