Oracle中含常数的复合索引

原来对于索引的认识只知道索引可以基于一个或者多个列,B-Tree索引不包含null,但有些情况下我们又需要通过where 列名 is null来查找一些数据,这时候数据库由于没办法使用索引就会使用全表扫描,导致执行效率低下,这时候我们可以通过使用含常数的复合索引来解决这个问题。

下面开始进行实验:

首先建立测试表

SYS@ORCL>create table test_objects nologging as select rownum id,a.* from dba_objects a where 1=2;

Table created.

插入500万条数据:

SYS@ORCL>declare

 l_cnt number;

 l_rows number:=&1;

begin

 insert /*+ append */ into test_objects select rownum,a.* from dba_objects a;

 l_cnt:=sql%rowcount;

 commit;

 while(l_cnt<l_rows)

 loop

   insert /*+ append */ into test_objects select rownum+l_cnt,

          owner,object_name,subobject_name,

          object_id,data_object_id,

          object_type,created,last_ddl_time,

          timestamp,status,temporary,

          generated,secondary

          from test_objects

          where rownum<=l_rows-l_cnt;

          l_cnt:=l_cnt+sql%rowcount;

    commit;

  end loop;

end;  2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21  

22  /

Enter value for 1: 5000000

old   3:   l_rows number:=&1;

new   3:   l_rows number:=5000000;

PL/SQL procedure successfully completed.

在object_id列上建立一般的B-Tree索引:

SYS@ORCL>create index idx_oid_test_objects on test_objects(object_id);

Index created.

收集表信息:

SYS@ORCL>exec dbms_stats.gather_table_stats('SYS','TEST_OBJECTS');    

PL/SQL procedure successfully completed.

测试一下索引能否正常使用:

SYS@ORCL>select count(*) from test_objects where object_id=52457;

 COUNT(*)

----------

       99

Execution Plan

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

Plan hash value: 3877533889

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

----------

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

Time     |

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

----------

|   0 | SELECT STATEMENT  |                      |     1 |     5 |     3   (0)|

00:00:01 |

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

        |

|*  2 |   INDEX RANGE SCAN| IDX_OID_TEST_OBJECTS |    99 |   495 |     3   (0)|

00:00:01 |

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

----------

Predicate Information (identified by operation id):

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

  2 - access("OBJECT_ID"=52457)

Statistics

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

         1  recursive calls

         0  db block gets

         3  consistent gets

         0  physical reads

         0  redo size

       411  bytes sent via SQL*Net to client

       385  bytes received via SQL*Net from client

         2  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

         1  rows processed

可以看到索引可以正常使用,下面我们来进入正题,当where条件中为object_id is null的时候会如何:

SYS@ORCL>select count(*) from test_objects where object_id is null;

 COUNT(*)

----------

        0

Execution Plan

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

Plan hash value: 3799704240

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

---

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

 |

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

---

|   0 | SELECT STATEMENT   |              |     1 |     5 | 16612   (2)| 00:03:2

0 |

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

 |

|*  2 |   TABLE ACCESS FULL| TEST_OBJECTS |     1 |     5 | 16612   (2)| 00:03:2

0 |

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

---

Predicate Information (identified by operation id):

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

  2 - filter("OBJECT_ID" IS NULL)

Statistics

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

         1  recursive calls

         0  db block gets

     74808  consistent gets

     74730  physical reads

       904  redo size

       410  bytes sent via SQL*Net to client

       385  bytes received via SQL*Net from client

         2  SQL*Net roundtrips to/from client

         0  sorts (memory)

         0  sorts (disk)

         1  rows processed

因为B-Tree索引不会记录null所以只能使用全表扫描。产生了大量的consistent gets下面我们来建立含常数的复合索引,并查询执行:

SYS@ORCL>create index idx_oid2_test_objects on test_objects(object_id,1);

Index created.

SYS@ORCL>select count(*) from test_objects where object_id is null;

 COUNT(*)

----------

时间: 2024-11-08 22:32:57

Oracle中含常数的复合索引的相关文章

oracle中如何使用视图,索引,存储过程。 就是说怎么去用或者用在什么地方,请指教

问题描述 oracle中如何使用视图,索引,存储过程. 就是说怎么去用或者用在什么地方,请指教 oracle中如何使用视图,索引,存储过程. 就是说怎么去用或者用在什么地方,请指教 解决方案 具体你去看书,这里只是简单说说:视图,相当于虚拟的表,你可以把不同的表连接起来得到一个视图,直接像表那样返回数据,而不用写复杂的查询了.索引,顾名思义,对表中的数据预处理,加快查询的速度.存储过程,一组预先写好的sql代码的集合,可以直接调用.存储过程因为是事先写好,并且编译的,所以更快,而且它像函数那样,

Oracle中如何把表和索引放在不同的表空间里

Oracle中并没有区分表空间里放的是表还是索引,所有当数据量比较小时,完全可以把表和索引放在同一个表空间里,但随着数据量的增大,最好还是把表和索引分开存储在不同的表空间里   因为:1)提高性能:尽量把表和索引的表空间存储在不同在磁盘上,把两类不同IO性质的数据分开放,这样可以提高磁盘的IO总体性能: 2)便于管理:试想一下,如果索引的数据文件损坏,只要创建索引即可,不会引起数据丢失的问题. 下面语句用于移动索引的表空间: 复制代码 代码如下: alter index INDEX_OWNER.

Oracle中唯一约束和唯一索引的区别

在使用TOAD来操作Oracle数据库时,会注意到创建约束时有Primary Key.Check.Unique和Foreign Key四种类型的约束,这与SQL Server中的约束没有什么区别,这里的Check约束除了用于一般的Check约束外,在Oracle中也用于非空约束的实现.也就是说如果一个字段不允许为空,则系统将会创建一个系统的Check约束,该约束定了某字段不能为空. 除了约束,还有另外一个概念是索引,在TOAD中创建索引的界面如下: 我们可以注意到在唯一性组中有三个选项:不唯一.

ORACLE中关于外键缺少索引的探讨和总结

    在ORACLE数据库中,定义外键约束时,ORACLE是不会自动创建对应索引的,必须手动在外键约束相关的列上创建索引.那么外键字段上是否有必要创建索引呢?如果有必要的话,巡检时,如何找出外键字段上没有创建索引的相关表,并生成对应的索引的脚本呢?   外键缺失索引影响   外键列上缺少索引会带来三个问题,限制并发性.影响性能.还有可能造成死锁.所以对于绝大部分场景,我们应该尽量考虑在外键上面创建索引   1. 影响性能. 如果子表外键没有创建索引,那么当父表查询关联子表时,子表将进行全表扫描

Oracle中检查是否需要重构索引的sql_oracle

复制代码 代码如下: SELECT height, /*Height of the B-Tree*/ blocks, /* Blocks in the index segment */ name, /*index name */ lf_rows, /* number of leaf rows in the index */ lf_blks, /* number of leaf blocks in the index */ del_lf_rows, /* number of deleted lea

Oracle中如何把表和索引放在不同的表空间里_oracle

因为:1)提高性能:尽量把表和索引的表空间存储在不同在磁盘上,把两类不同IO性质的数据分开放,这样可以提高磁盘的IO总体性能: 2)便于管理:试想一下,如果索引的数据文件损坏,只要创建索引即可,不会引起数据丢失的问题. 下面语句用于移动索引的表空间: 复制代码 代码如下: alter index INDEX_OWNER.INDEX_NAME rebuild tablespace NEW_TBS; 也可以利用以下语句获得某个schema下移动索引表空间的所有语句: 复制代码 代码如下: selec

ORACLE中死锁的知识点总结

  死锁的概念       什么是死锁呢? 其实我们生活中也有很多类似死锁的例子. 我先举一个生活中的例子:过年回家,父亲买了一把水弹枪,儿子和侄子争抢着要先玩,谁也不让谁,拆开包装后,一个抢了枪, 一个逮住了子弹和弹夹.两个都争着要先玩,但是都互不相让.结果两个人都玩不了.如果儿子要先玩,就必须让侄子把子弹和弹夹给他,如果侄子要先玩,就必须让儿子把枪给侄子.他们就这样对峙了十几分钟,互不相让. 我出来调停,让儿子把枪先给侄子玩,每个人玩十分钟.然后两个人开开心心一起玩起来.其实这就是一个活生生

Oracle中常数复合索引的应用案例

从一个客户的真实优化案例引申的问题. 客户的一个数据库需要进行优化,不过由于程序开发方没有介入,因此这次优化无法对SQL进行修改. 仅对数据库级的调整一般来说收效不大,不过发现客户数据库中个别的SQL存在性能问题,且这个性能问题已经影响到整个数据库.如果可以将这个SQL优化,那么可以解决目前数据库的性能问题.幸运的是,这个问题可以通过添加索引来进行优化. 模拟问题SQL如下: SQL> select * from v$version; BANNER -----------------------

oracle中复合索引的创建剖析—包含in的三个条件SQL语句复合索引的创建

之前文章中提过复合索引的创建思路: 1 前导列尽可能让更多的核心业务SQL能够使用 2 单个SQL语句索引的前导列尽量选择等值条件做为索引的前导列 这里我们如果在对in的谓词.三个条件的SQL语句复合索引的创建做一些更深入的分析,详细的例子如下: SQL> select * from v$version; BANNER -------------------------------------------------------------------------------- Oracle D