通过案例学调优之--Oracle中null使用索引

通过案例学调优之--Oracle中null使用索引

 默认情况下,Oracle数据库,null在Index上是不被存储的,当在索引列以“is null”的方式访问时,无法使用索引;本案例,主要向大家演示如何在存在null的索引列上,使用“is null”访问索引。

案例分析:


1、建立表和普通索引

13:52:23 [email protected] prod >create table t2 (x int,y int);
Table created.
14:00:11 [email protected] prod >insert into t2 values (1,1);
1 row created.
Elapsed: 00:00:00.04
14:00:21 [email protected] prod >insert into t2 values (1,null);
1 row created.
Elapsed: 00:00:00.00
14:00:31 [email protected] prod >insert into t2 values (null,1);
1 row created.
Elapsed: 00:00:00.00
14:00:37 [email protected] prod >insert into t2 values (null,null);
1 row created.
Elapsed: 00:00:00.00
14:00:44 [email protected] prod >commit;
Commit complete.
Elapsed: 00:00:00.04
14:06:41 [email protected] prod >select * from t2;
         X          Y
---------- ----------
         1          1
         1
                    1
                    
14:36:12 [email protected] prod >create index t2_ind on t2(x);
Index created.

14:49:38 [email protected] prod >select index_name,table_name,num_rows from user_indexes where index_name=‘T2_IND‘;
INDEX_NAME                     TABLE_NAME                       NUM_ROWS
------------------------------ ------------------------------ ----------
T2_IND                         T2                                      3

  在索引中只有3行,在最后一行字段全为null值,没有被存储!

14:36:27 [email protected] prod >exec dbms_stats.gather_index_stats(user,‘T2_IND‘);
PL/SQL procedure successfully completed.

14:37:29 [email protected] prod >select * from t2 where x=1;
         X          Y
---------- ----------
         1          1
         1

Execution Plan
----------------------------------------------------------
Plan hash value: 1173409066
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     2 |     8 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2     |     2 |     8 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T2_IND |     2 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("X"=1)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
        519  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
          
14:37:45 [email protected] prod >select * from t2 where x is not null;
         X          Y
---------- ----------
         1          1
         1

Execution Plan
----------------------------------------------------------
Plan hash value: 463061910
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     2 |     8 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2     |     2 |     8 |     2   (0)| 00:00:01 |
|*  2 |   INDEX FULL SCAN           | T2_IND |     2 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("X" IS NOT NULL)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
        519  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
          
14:38:00 [email protected] prod >select * from t2 where x is null;
         X          Y
---------- ----------
                    1

Execution Plan
----------------------------------------------------------
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     2 |     8 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T2   |     2 |     8 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("X" IS NULL)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
        508  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
当x通过“is null”访问时,Oracle选择了“full table”方式。

2、通过建立常量符合索引

14:38:55 [email protected] prod >create index t2_ind on t2(x,0);
Index created.

14:49:38 [email protected] prod >select index_name,table_name,num_rows from user_indexes where index_name=‘T2_IND‘;
INDEX_NAME                     TABLE_NAME                       NUM_ROWS
------------------------------ ------------------------------ ----------
T2_IND                         T2                                      4

   索引块上存储了表中所用的行。

14:39:50 [email protected] prod >select * from t2 where x is null;
         X          Y
---------- ----------
                    1
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
Plan hash value: 1173409066
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     2 |     8 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2     |     2 |     8 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T2_IND |     2 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("X" IS NULL)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
        508  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
          
对于x通过“is null”访问时,也能通过索引访问了!

3、建立复合索引(其他列为null)

13:59:40 [email protected] prod >create index x_ind on t2(x,y);
Index created.

14:08:29 [email protected] prod >EXEC dbms_stats.gather_table_stats(ownname=>USER,tabname=>‘T2‘);
PL/SQL procedure successfully completed.

14:09:22 [email protected] prod >EXEC dbms_stats.gather_index_stats(ownname=>USER,indname=>‘X_IND‘);
PL/SQL procedure successfully completed.

14:09:58 [email protected] prod >select index_name,num_rows from user_indexes where index_name=‘X_IND‘;
INDEX_NAME                       NUM_ROWS
------------------------------ ----------
X_IND                                   3

14:10:50 [email protected] prod >select count(*) from t2;
  COUNT(*)
----------
         4
         
14:11:28 [email protected] prod >set autotrace on
14:12:33 [email protected] prod >select * from t2 where x=1;
         X          Y
---------- ----------
         1          1
         1

Execution Plan
----------------------------------------------------------
Plan hash value: 3708139238
--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     2 |     8 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| X_IND |     2 |     8 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("X"=1)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        512  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
          
14:12:47 [email protected] prod >select * from t2 where x is not null;
         X          Y
---------- ----------
         1          1
         1
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
Plan hash value: 3776680409
--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     2 |     8 |     1   (0)| 00:00:01 |
|*  1 |  INDEX FULL SCAN | X_IND |     2 |     8 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("X" IS NOT NULL)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        512  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
          
14:13:08 [email protected] prod >select * from t2 where x is null;
         X          Y
---------- ----------
                    1
Execution Plan
----------------------------------------------------------
Plan hash value: 1513984157
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     2 |     8 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T2   |     2 |     8 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("X" IS NULL)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
        508  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
          
 如果,复合索引列其他列也为null,在查询使用’is null‘条件时,仍然为“full table scan”。
          
14:13:52 [email protected] prod >select * from t2 where x=1 and y is null;
         X          Y
---------- ----------
         1

Execution Plan
----------------------------------------------------------
Plan hash value: 3708139238
--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |     4 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| X_IND |     1 |     4 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("X"=1 AND "Y" IS NULL)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        471  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
          
14:16:16 [email protected] prod >select * from t2 where x is null and y=1;
         X          Y
---------- ----------
                    1

Execution Plan
----------------------------------------------------------
Plan hash value: 3708139238
--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |     4 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| X_IND |     1 |     4 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("X" IS NULL AND "Y"=1)
       filter("Y"=1)
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          1  consistent gets
          0  physical reads
          0  redo size
        471  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

4、建立复合索引(其他列为 not null)

15:13:38 [email protected] prod >desc t2;
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 X                                                                          NUMBER(38)
 Y                                                                          NUMBER(38)
 
15:13:43 [email protected] prod >alter table t2 modify (y NUMBER(38) not null);
Table altered.

15:14:01 [email protected] prod >desc t2;
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 X                                                                          NUMBER(38)
 Y                                                                 NOT NULL NUMBER(38)
 
15:12:54 [email protected] prod >insert into t2 values (1,1);
1 row created.
Elapsed: 00:00:00.02
15:13:02 [email protected] prod >insert into t2 values (null,1);
1 row created.
Elapsed: 00:00:00.00
15:13:12 [email protected] prod >insert into t2 values (null,2);
1 row created.
Elapsed: 00:00:00.00
15:13:36 [email protected] prod >commit;
Commit complete.

15:15:00 [email protected] prod >create index t2_ind on t2 (x,y);
Index created.

15:15:29 [email protected] prod >exec dbms_stats.gather_table_stats(user,‘T2‘,cascade=>true);
PL/SQL procedure successfully completed.

15:16:09 [email protected] prod >select index_name,table_name,num_rows from user_indexes where index_name=‘T2_IND‘;
INDEX_NAME                     TABLE_NAME                       NUM_ROWS
------------------------------ ------------------------------ ----------
T2_IND                         T2                                      3

15:17:20 [email protected] prod >set autotrace trace
15:17:26 [email protected] prod >SELECT * from t2 where x is null
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
Plan hash value: 2876512201
---------------------------------------------------------------------------
| Id  | Operation        | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT |        |     2 |    10 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| T2_IND |     2 |    10 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("X" IS NULL)
Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        510  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
在复合索引中,如果其他列为not null,则在“is null”条件下,仍然可以使用索引访问。

结论:

对于普通的索引,null值不能进行索引的正确理解应该是,对于某一行,索引的所有列的值都是null值时,该行才不能被索引。


时间: 2024-10-25 16:29:36

通过案例学调优之--Oracle中null使用索引的相关文章

通过案例学调优之--Oracle Time Model(时间模型)

通过案例学调优之--Oracle Time Model(时间模型) 数据库时间  优化不仅仅是缩短等待时间.优化旨在缩短最终用户响应时间和(或)尽可能减少每个请求占用的平均资源.有时这些目标可同时实现,而有时则需要进行折衷(如在并行查询时).通常可以认为,优化就是避免以浪费的方式占用或保留资源. 对数据库发出的任何请求都由两个不同的段组成:等待时间(数据库等待时间)和服务时间(数据库 CPU 时间).等待时间是各种数据库实例资源的所有等待时间的总和.CPU 时间是实际处理请求时消耗的时间的总和.

通过案例学调优之--Oracle 全文索引

通过案例学调优之--Oracle 全文索引 全文检索(oracle text)  Oracle Text使Oracle9i具备了强大的文本检索能力和智能化的文本管理能力,Oracle Text 是 Oracle9i 采用的新名称,在 oracle8/8i 中被称为 oracle intermedia text,oracle8 以前是 oracle context cartridge.Oracle Text 的索引和查找功能并不局限于存储在数据库中的数据. 它可以对存储于文件系统中的文档进行检索和

通过案例学调优之--Oracle参数(db_file_multiblock_read_count)

通过案例学调优之--Oracle参数(db_file_multiblock_read_count) 应用环境: 操作系统: RedHat EL55 Oracle:   Oracle 10gR2   Oracle DB_FILE_MULTIBLOCK_READ_COUNT是Oracle比较重要的一个全局性参数,可以影响系统级别及sessioin级别.主要是用于设置最小化表扫描时Oracle一次按顺序能够读取的数据块数.通常情况下,我们看到top events中的等待事件db file scatte

通过案例学调优之--Oracle Cluster Table

通过案例学调优之--Oracle Cluster Table About Clusters A cluster provides an optional method of storing table data. A cluster is made up of a group of tables that share the same data blocks. The tables are grouped together because they share common columns an

通过案例学调优之--Oracle数据块(block)

数据块概述Oracle对数据库数据文件(datafile)中的存储空间进行管理的单位是数据块(data block).数据块是数据库中最小的(逻辑)数据单位.与数据块对应的,所有数据在操作系统级的最小物理存储单位是字节(byte).每种操作系统都有一个被称为块容量(block size)的参数.Oracle每次获取数据时,总是访问整个数(Oracle)数据块,而不是按照操作系统块的容量访问数据. 数据库中标准的数据块(data block)容量是由初始化参数 DB_BLOCK_SIZE 指定的.

[性能调优]在PeopleSoft中使用函数索引

那些没有在PeopleSoft系统遇到性能问题的人,特别是基于Oracle数据库的PeopleSoft,可能不知道基于函数的索引. 根据定义,基于函数的索引是使用如下方法定义的: 基于表达式,例如算术表达式或包含函数的表达式 基于降序列(descending ordered column) 然后还有一种叫做函数索引的的表达式,这些索引是包含在索引列周围的表达式的索引.他们在PeopleSoft中非常罕见,为了提高特定SQL语句的性能而创建. 例如PS_NAMES表,有一个索引PS4NAMES中字

通过案例学调优之--AWR BaseLine管理

通过案例学调优之--AWR BaseLine管理 BaseLine Baseline 是指一个特定时间段内的性能数据,保留这些数据是为了在性能问题产生时与其他类似的工作负载时间段进行比较.Baseline 中包含的快照将从自动 AWR 清理进程中排除,并无限期的保留. 在 Oracle Database 中存在多种类型的 baseline:      Fixed Baseline:fixed baseline 表示的是您指定的一个固定的.连续的时间段.在创建 fixed baseline 之前,

通过案例学调优之--SQL Profile

通过案例学调优之--SQL Profile 一.什么是SQL Profile(概要) SQL Profile在性能优化中占有一个重要的位置. MOS里这么描述SQL Profile: SQL Profile是10g中的新特性,作为自动SQL调整过程的一部分,由Oracle企业管理器来管理.除了OEM,SQL Profile可以通过DBMS_SQLTUNE包来进行管理. 查询优化器有时候会因为缺乏足够的信息,而对一条SQL语句做出错误的估计,生成糟糕的执行计划.而自动SQL调整通过SQL概要分析来

通过案例学调优之--AWR基本概念

通过案例学调优之--AWR基本概念 一.Automatic Workload Repository 概念详解 Automatic Workload Repository (AWR) 收集.处理和维护用于问题诊断的性能统计信息.该数据既存在于数据块中,也存在于内存中.AWR 收集的数据可以通过报告和视图进行查看. AWR 处理和收集的统计信息包括: 1.确定数据块 segment 访问路径和使用情况的对象统计信息 2.基于数据库活动的时间使用情况的时间模型统计信息,可在 V$SYS_TIME_MO