eygle.com   eygle.com
eygle.com  
 

« 使用Index提示 强制使用索引 | Blog首页 | 要发现人家的优点你才会觉得幸福 »

索引与Null值对于Hints及执行计划的影响

作者:eygle |【转载时请务必以超链接形式标明文章和作者信息及本声明
链接:

由于B*Tree索引不存储Null值,所以在索引字段允许为空的情况下,某些Oracle查询不会使用索引.

很多时候,我们看似可以使用全索引扫描(Full Index Scan)的情况,可能Oracle就会因为Null值的存在而放弃索引.

在此情况下即使使用Hints,Oracle也不会使用索引,其根本原因就是因为Null值的存在.

我们看以下测试.

username字段为Not Null时,Index Hints可以生效.

SQL> create table t as select username,password from dba_users;
Table created.
SQL> desc t
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 USERNAME                                  NOT NULL VARCHAR2(30)
 PASSWORD                                           VARCHAR2(30)
SQL> create index i_t on t(username);
Index created.
SQL> set autotrace trace explain
SQL> select * from t where username='EYGLE';
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    34 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |     1 |    34 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("USERNAME"='EYGLE')
Note
-----
   - dynamic sampling used for this statement
SQL> set linesize 120
SQL> select /*+ index(t,i_t) */ * from t where username='EYGLE';
Execution Plan
----------------------------------------------------------
Plan hash value: 2928007915
------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |     1 |    34 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T    |     1 |    34 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_T  |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("USERNAME"='EYGLE')
Note
-----
   - dynamic sampling used for this statement

当索引字段允许为Null时,Oracle放弃此索引:

SQL> alter table t modify (username null);
Table altered.
SQL> select /*+ index(t,i_t) */ * from t;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    27 |   918 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T    |    27 |   918 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------
Note
-----
   - dynamic sampling used for this statement 

当该字段为Not Null时,索引可以被强制使用:

SQL> alter table t modify (username not null);
Table altered.
SQL> select /*+ index(t,i_t) */ * from t;
Execution Plan
----------------------------------------------------------
Plan hash value: 3593393735
------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |    27 |   918 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T    |    27 |   918 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN           | I_T  |    27 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------
Note
-----
   - dynamic sampling used for this statement
 

这就是Null值对于索引及查询的影响.

 

-----
这篇 【索引与Null值对于Hints及执行计划的影响】来自 www.eygle.com | CSDN技术网摘| del.icio.us|365Key

By eygle on 2006-02-22 17:19 | Comments (4) | Posted to SQL.PLSQL | Edit |Pageviews:

相关文章 随机文章
  • 使用Index提示 强制使用索引
  • 基于自定义函数的Function-Based索引创建
  • Oracle Patch Set Note And Bug List 参考
  • Oracle的分区表和Local索引创建与维护
  • Oracle 9i 的生命周期支持策略
  • Oracle9i自动PGA管理的新特性
    Oracle10g数据字典演示Flash下载
    北飞的候鸟-Kamus北京庭审现场
    我的写作进度
    Oracle广州招聘DB方面的售前工程师
    网上相关主题:
    Google

    留言 (4)

    测试.

    Posted by: eygle at February 23, 2006 9:48 AM

    ref:"由于B*Tree索引不存储Null值,所以在索引字段允许为空的情况下,Oracle查询不会使用索引."
    这种情况只影响强制使用索引hints而又无此字段的where条件时,当select语句中的where条件包含此字段的expression时一样可以使用此索引!
    反之,按本文的说法,我们岂不是只能在非空字段上建索引了?!事实是我们可以在我们任意想要建索引的字段上建索引,只要你认为必要,无需关注其是否not null!
    不同的是,is null条件是当然是不查B*Tree索引的,Bitmap索引则可以。

    Posted by: xsb at February 28, 2006 10:28 AM

    ref:"由于B*Tree索引不存储Null值,所以在索引字段允许为空的情况下,Oracle查询不会使用索引."
    这种情况只影响强制使用索引hints而又无此字段的where条件时,当select语句中的where条件包含此字段的expression时一样可以使用此索引!
    反之,按本文的说法,我们岂不是只能在非空字段上建索引了?!事实是我们可以在我们任意想要建索引的字段上建索引,只要你认为必要,无需关注其是否not null!
    不同的是,is null条件当然是不查B*Tree索引的,Bitmap索引则可以。

    Posted by: xsb at February 28, 2006 10:30 AM

    你说的不错,这句话说起来很绕口,当初没有说的严谨.

    谢谢指出.

    Posted by: eygle at February 28, 2006 10:41 AM

    发表留言:



    Remember Me?
    (输入验证码后方可评论,谢谢支持)



    CopyRight © 2004 eygle.com, All rights reserved.