我们知道,Oracle软件最核心的组件就是优化器,可以说他决定了一条SQL能否正确执行的路径,这两天就碰到了一个场景。
创建测试表,插入两条测试的数据,
SQL> create table t_null (id number, name varchar2(1));
Table created.
SQL> insert into t_null values(1, '');
1 row created.
SQL> insert into t_null values(2, 'a');
1 row created.
SQL> commit;
Commit complete.
SQL>
ID N
---------- -
1
2 a
此时,如果按照id判断是否为空的操作,如下所示,谓词信息是id is null,
select * from t_Null where id is null;
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 15 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T_NULL | 1 | 15 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID" IS NULL)
如果我们将id设置非空约束,会出现什么现象?
SQL> alter table t_Null modify id not null;
Table altered.
谓词信息改成了null is not null,预估Cost=0,
select * from t_Null where id is null;
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 15 | 0 (0) | |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| T_NULL | 2 | 30 | 3 (0) | 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NULL IS NOT NULL)
null is not null,明显是个不成立的条件,相当于此处Oracle做了一个“短路”的处理,从逻辑上说,id字段,不可能存在空值,where使用id is null就是个无意义的操作,返回肯定是空,既然如此,不需要消耗资源为了得到一个已经确定的结果,因此直接使用了这个“短路”条件,结束了这次执行。
优化器的处理,还是很具备逻辑性的,值得学习。