今天在优化sql语句的时候发现存在如下sql语句,像这样
select * from t where object_name='' ;
发现执行计划里面存在全表扫描,这个问题主要在与开发人员没有判断输入的条件。
自己写了一个测试例子,如下:
1。建立表以及索引:
create table t as select * from all_objects ;
create index i_t_object_name on t(object_name);
2。分析表
BEGIN
SYS.DBMS_STATS.GATHER_TABLE_STATS (
OwnName => 'SCOTT'
,TabName => 'T'
,Cascade => TRUE);
END;
3.测试:
set autotrace traceonly
select * from t where object_name='' ;
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 1322348184
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 128 | 0 (0)| |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| T | 44358 | 5544K| 149 (3)| 00:00:02 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(NULL IS NOT NULL)
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
913 bytes sent via SQL*Net to client
323 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
开始对consistent gets为0很不理解,实际上在filter上已经说明条件是NULL IS NOT NULL,
这个条件永远为假。可以这个看在输入这个条件object_name=''时,oracle将''看成NULL,
如果输入如下条件object_name=NULL或者NULL=NULL,结果也是一样的,这个也可以说明
oracle中NULL不等于NULL。要真正查找NULL要写成 select * from t where object_name
is NULL ;
在来看这个执行结果,先修改表t的object_name字段让它不为NULL(实际上建立T表时已经定义):
ALTER TABLE T MODIFY(object_name NOT NULL);
select * from t where object_name is NULL ;
执行计划的filter还是,1 - filter(NULL IS NOT NULL)。
如果修改字段属性object_name为NULL
ALTER TABLE T MODIFY(object_name NULL);
执行计划的变为1 - filter("OBJECT_NAME" IS NULL)。