文章标题

来源:互联网 发布:淘宝如何减少竞店流失 编辑:程序博客网 时间:2024/06/18 03:57
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
原创粉丝点击