关于创建含null值索引与含null值的复合索引

Null值索引

准备样表

SCOTT@PROD>create table t as select * from all_objects;

 

Table created.

 

SCOTT@PROD>select count(*) from t;         

 

  COUNT(*)

----------

      5985

 

SCOTT@PROD>update t set OBJECT_TYPE=null where OBJECT_TYPE='INDEX';

 

2 rows updated.

 

我们建立一个普通的单列索引

SCOTT@PROD>create index t_obj_type_idx on t(OBJECT_TYPE);  

 

Index created.

 

 

 

SCOTT@PROD>set autot traceonly;

SCOTT@PROD>select count(*) from t where OBJECT_TYPE is null;

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 2966233522

 

---------------------------------------------------------------------------

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

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    11 |    25   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |      |     1 |    11 |            |          |

|*  2 |   TABLE ACCESS FULL| T    |     1 |    11 |    25   (0)| 00:00:01 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("OBJECT_TYPE" IS NULL)

 

Note

-----

   - dynamic sampling used for this statement (level=2)

 

 

Statistics

----------------------------------------------------------

          0  recursive calls

          0  db block gets

         82  consistent gets

          0  physical reads

          0  redo size

        526  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

可见普通的单列索引无法记录null

 

 

SCOTT@PROD>drop index t_obj_type_idx;

 

Index dropped.

 

我们建立一个复合索引,第二列为常数值,常数列没有意义,但是在有常数列的情况下,第一列的null会录入index

SCOTT@PROD>create index t_obj_type_idx on t(OBJECT_TYPE,1);

 

Index created.

 

SCOTT@PROD>select count(*) from t where OBJECT_TYPE is null;

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3976877961

 

--------------------------------------------------------------------------------

----

 

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

   |

 

--------------------------------------------------------------------------------

----

 

|   0 | SELECT STATEMENT  |                |     1 |    11 |     3   (0)| 00:00:

01 |

 

|   1 |  SORT AGGREGATE   |                |     1 |    11 |            |

   |

 

|*  2 |   INDEX RANGE SCAN| T_OBJ_TYPE_IDX |     1 |    11 |     3   (0)| 00:00:

01 |

 

--------------------------------------------------------------------------------

----

 

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("OBJECT_TYPE" IS NULL)

 

Note

-----

   - dynamic sampling used for this statement (level=2)

 

 

Statistics

----------------------------------------------------------

         25  recursive calls

          0  db block gets

        102  consistent gets

          1  physical reads

          0  redo size

        526  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

我们再尝试一下一般的复合索引

SCOTT@PROD>create index t_obj_type_idx on t(OBJECT_TYPE,OBJECT_NAME);

 

Index created.

 

SCOTT@PROD>set autot traceonly;

SCOTT@PROD>select count(*) from t where OBJECT_TYPE is null;

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3976877961

 

--------------------------------------------------------------------------------

----

 

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

   |

 

--------------------------------------------------------------------------------

----

 

|   0 | SELECT STATEMENT  |                |     1 |    11 |     3   (0)| 00:00:

01 |

 

|   1 |  SORT AGGREGATE   |                |     1 |    11 |            |

   |

 

|*  2 |   INDEX RANGE SCAN| T_OBJ_TYPE_IDX |     1 |    11 |     3   (0)| 00:00:

01 |

 

--------------------------------------------------------------------------------

----

 

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("OBJECT_TYPE" IS NULL)

 

Note

-----

   - dynamic sampling used for this statement (level=2)

 

 

Statistics

----------------------------------------------------------

         25  recursive calls

          0  db block gets

        102  consistent gets

          1  physical reads

          0  redo size

        526  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

可见复合索引含null值在首列的情况下 ,null值会被记录进index

 

那不在首列的情况下,是否会被记录呢

SCOTT@PROD>create index t_idx on t(OWNER,OBJECT_TYPE);

 

Index created.

 

SCOTT@PROD>select count(*) from t where OWNER='SYS' and OBJECT_TYPE is null;

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 1058879072

 

-------------------------------------------------------------------------------

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

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT      |       |     1 |    28 |     9   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE       |       |     1 |    28 |            |          |

|*  2 |   INDEX FAST FULL SCAN| T_IDX |     3 |    84 |     9   (0)| 00:00:01 |

-------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("OBJECT_TYPE" IS NULL AND "OWNER"='SYS')

 

Note

-----

   - dynamic sampling used for this statement (level=2)

 

 

Statistics

----------------------------------------------------------

         25  recursive calls

          0  db block gets

        125  consistent gets

         20  physical reads

          0  redo size

        525  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

可见复合索引是会记录null值的

 

附:

何时oracle会通过复合索引查询复合索引上的非首列

复合索引上的非首列单独作为谓词的过滤条件时,大部分情况下是不能走索引的,但是万事有例外

 

SCOTT@PROD>select count(*) from t where OBJECT_TYPE='VIEW';

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 1058879072

 

-------------------------------------------------------------------------------

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

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT      |       |     1 |    11 |     9   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE       |       |     1 |    11 |            |          |

|*  2 |   INDEX FAST FULL SCAN| T_IDX |  1245 | 13695 |     9   (0)| 00:00:01 |

-------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("OBJECT_TYPE"='VIEW')

 

Note

-----

   - dynamic sampling used for this statement (level=2)

 

 

Statistics

----------------------------------------------------------

          5  recursive calls

          0  db block gets

         88  consistent gets

          0  physical reads

          0  redo size

        527  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

可见走了索引,这其实是聚集函数的原因,count*)只查询记录数,不需要回表

 

SCOTT@PROD>select * from t where OBJECT_TYPE is null;

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 1601196873

 

--------------------------------------------------------------------------

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

--------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |      |     1 |   158 |    25   (0)| 00:00:01 |

|*  1 |  TABLE ACCESS FULL| T    |     1 |   158 |    25   (0)| 00:00:01 |

--------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   1 - filter("OBJECT_TYPE" IS NULL)

 

Note

-----

   - dynamic sampling used for this statement (level=2)

 

 

Statistics

----------------------------------------------------------

          5  recursive calls

          0  db block gets

        146  consistent gets

          0  physical reads

          0  redo size

       1736  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          2  rows processed

 

可见在不使用聚集函数时,是无法使用符合索引的

 

 

SCOTT@PROD>select sum(object_id) from t where OBJECT_TYPE is null;

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 2966233522

 

---------------------------------------------------------------------------

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

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    24 |    25   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE    |      |     1 |    24 |            |          |

|*  2 |   TABLE ACCESS FULL| T    |     1 |    24 |    25   (0)| 00:00:01 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("OBJECT_TYPE" IS NULL)

 

Note

-----

   - dynamic sampling used for this statement (level=2)

 

 

Statistics

----------------------------------------------------------

          4  recursive calls

          0  db block gets

        145  consistent gets

          0  physical reads

          0  redo size

        534  bytes sent via SQL*Net to client

        523  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

使用了聚集函数还是不走索引,说明真正的原因是索引回表,当没有索引回表时,符合索引的非首列在单独作为过滤条件时是会走索引的

你可能感兴趣的:(关于创建含null值索引与含null值的复合索引)