讨论B树索引中的 is null/is not null

为什么在查询中使用IS NULL 或IS NOT NULL同样会限制索引的使用

简答的说因为索引键值不会存储空值

Oracle的CBO并不会因为SQL语句中指定了IS NOT NULL或IS NULL操作就不再使用索引。CBO选择索引的条件只有正确性和代价,只要满足这两个条件就可以了。

测试案例

以dba_objects表的数据建一个测试表为T  

create table t as select * from dba_objects;
将data_object_id=2的object_name列更改为null
update t set object_name =null where data_object_id=2 and  (object_id <20 or object_id>20)
创建object_name列的索引
create index index_objecton on t(object_name)

B树索引不存储键值全为空的记录。所以对于单列索引而言,确实IS NULL操作是无法使用索引的

—————————————————————————————————-

SQL>  select count(*) from t where object_name is null;            ———走的是全表扫描

Execution Plan

———————————————————-

Plan hash value: 2966233522

—————————————————————————

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

—————————————————————————

|   0 | SELECT STATEMENT   |      |     1 |    25 |   283   (1)| 00:00:04 |

|   1 |  SORT AGGREGATE    |      |     1 |    25 |            |          |

|*  2 |   TABLE ACCESS FULL| T    |    17 |   425 |   283   (1)| 00:00:04 |

—————————————————————————

Predicate Information (identified by operation id):

—————————————————

   2 – filter(“OBJECT_NAME” IS NULL)

Statistics

———————————————————-

          1  recursive calls

          0  db block gets

       1038  consistent gets

       1035  physical reads

          0  redo size

        422  bytes sent via SQL*Net to client

        419  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

SQL>  select count(*) from t where object_name is not null;            —————-走的是索引,,

Execution Plan
———————————————————-
Plan hash value: 162321089

—————————————————————————————-

| Id  | Operation             | Name           | Rows  | Bytes | Cost (%CPU)| Time     |

—————————————————————————————-

|   0 | SELECT STATEMENT      |                |     1 |    25 |   100   (0)| 00:00:02 |

|   1 |  SORT AGGREGATE       |                |     1 |    25 |            |       |

|*  2 |   INDEX FAST FULL SCAN| INDEX_OBJECTON | 72749 |  1776K|   100   (0)| 00:00:02 |

—————————————————————————————-

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

   2 – filter(“OBJECT_NAME” IS NOT NULL)

Statistics
———————————————————-
          0  recursive calls
          0  db block gets
        371  consistent gets
          0  physical reads

          0  redo size
        424  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

—————————————————————————————————————————————————

复合索引是可能存储一部分NULL值的,所以,IS NULL操作也并非不可能使用索引。

测试环境

ALTER TABLE T MODIFY OWNER NOT NULL;   ———–修改字段类型   
UPDATE T SET OBJECT_ID = NULL WHERE ROWNUM = 1;
CREATE INDEX IND_T_OBJECT_OWNER ON T (OBJECT_ID, OWNER);      ——-创建组合索引
EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, ‘T’, METHOD_OPT => ‘FOR ALL INDEXED COLUMNS SIZE 200’)

SQL> select count(*) from t where object_id is null;      ————走索引

Execution Plan
———————————————————-
Plan hash value: 4092988493

—————————————————————————————-

| Id  | Operation         | Name               | Rows  | Bytes | Cost (%CPU)| Ti
me     |

—————————————————————————————-

|   0 | SELECT STATEMENT  |                    |     1 |     5 |     2   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE   |                    |     1 |     5 |            |       |

|*  2 |   INDEX RANGE SCAN| IND_T_OBJECT_OWNER |     1 |     5 |     2   (0)| 00:00:01 |

—————————————————————————————-

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

   2 – access(“OBJECT_ID” IS NULL)

Statistics
———————————————————-
          1  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        422  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

    原文作者:B树
    原文地址: https://blog.csdn.net/yftianxia/article/details/14053725
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞