Oracle索引组织表学习系列一

1 索引组织表(IOT Index-Organized Table)概述      
 

       在Oracle数据库中,有一类表被称之为索引组织表,即IOT(Index-Organized Table)。顾名思义,所谓的索引组织表,表面上看是一种表,实质上其数据是以索引的形式来存放的,也就是说IOT表不会占用表段,其占用的是索引段。

       相比较传统的堆表( heap-organized table,即常见的普通表)而言,IOT表的数据是以已经按主键字段排好序后存放在B-tree索引中的,而堆表的数据则是无序的存放在表段的数据块中。此外,在IOT的索引叶子节点块中,既存放主键字段数据,也存放非主键字段的值。

        一张IOT表同Heap表的对比示意图:

2 索引组织表(IOT Index-Organized Table)特征

 

       通过IOT表的主键字段来访问数据可以快速完成,因为IOT表的数据全部存放在B-Tree索引上,只需定位到索引上的数据即可,而无需再去像访问heap表那样进一步通过索引去定位表段上的数据;对IOT表执行DML操作,只会影响到B-Tree索引;

      通过IOT表的主键字段快速范围访问数据很快,因为记录已经是事先按主键排好序的;

      IOT表可以有效的降低存储开销,因为主键字段的数据只是存放在B-Tree索引上,并没有像heap那样,主键字段数据既存放在表段上,也存放在索引上;

      IOT表除了像Heap表那样可以支持约束、触发器、LOB字段、对象字段、分区、并行操作、在线重定义、复制操作等,还支持主键字段压缩、提供溢出存储段(Overflow storage area )、二次索引(Secondary indexes, including bitmap indexes)

 

3 创建索引组织表(IOT Index-Organized Table)

 

   创建IOT表时,必须包含下列2个从句:

        1 ORGANIZATION INDEX,用来标识该表是IOT表;

        2 在建表的同时要指定主键约束,可以是单字段主键,也可以是复合主键约束。

    创建IOT表时,也可以同时指定下列3个从句:

        1 OVERFLOW从句,用于标识非主键字段存放在独立的溢出存储段数据区

        2 PCTTHRESHOLD value,如果指定了溢出存储段的话,该值用于限定可以存放在索引数据块中的最大数据的百分比,即如果IOT表中的行记录超过该值的话,剩余的字段就存放在溢出存储段数据区。也就是说,IOT表中的一条记录有可能被拆分成两部分:头数据区(Head Piece)和尾数据区(Tail Piece)。将主键字段和不超过PCTTHRESHOLD限定的其它非主键字段存放在头数据区,而将其它的非主键字段存放在尾数据区。因此,此时的IOT表的索引记录存放的数据就成了主键字段+满足PCTTHRESHOLD限定的其它非主键字段+指针,指针指向剩余非主键字段存放的地址;PCTTHRESHOLD的取值范围是1-50,默认值是50;

        3 INCLUDING从句,用于显示声明哪些非主键字段可以和主键字段一起存放在索引数据块中。这样,剩下的非主键字段就会存放到独立的溢出存储段数据区。

     创建IOT表的一个示例:

OS版本:

[oracle@oracle11g ~]$ uname -rm
2.6.18-194.el5 x86_64
[oracle@oracle11g ~]$

Oracle版本:

SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

SQL> 

建表:

SQL> conn hr/hr
Connected.
SQL> CREATE TABLE admin_docindex(
  2  token char(20), 
  3  doc_id NUMBER,
  4  token_frequency NUMBER,
  5  token_offsets VARCHAR2(2000),
  6  CONSTRAINT pk_admin_docindex PRIMARY KEY (token, doc_id))
  7  ORGANIZATION INDEX 
  8  TABLESPACE admin_tbs
  9  PCTTHRESHOLD 20
 10  OVERFLOW TABLESPACE admin_tbs2;

Table created.

SQL> insert into ADMIN_DOCINDEX values('oracleonlinux.cn',1,1,'test iot table');

1 row created.

SQL> commit;

Commit complete.

SQL> 

查看该表的信息,可以看到该表不属于任何表空间,因为没有数据段:

SQL> select table_name,tablespace_name,iot_name,iot_type from user_tables where table_name='ADMIN_DOCINDEX';

TABLE_NAME                     TABLESPACE_NAME                IOT_NAME                       IOT_TYPE
------------------------------ ------------------------------ ------------------------------ ------------
ADMIN_DOCINDEX                                                                               IOT

SQL> select segment_name,segment_type,tablespace_name from user_segments where SEGMENT_NAME='ADMIN_DOCINDEX';

no rows selected

SQL> 

查看索引的信息,我们能看到索引反而占有表空间:

SQL> select index_name,index_type,table_name,tablespace_name,table_type ,PCT_THRESHOLD from user_indexes where table_name='ADMIN_DOCINDEX';

INDEX_NAME                     INDEX_TYPE                  TABLE_NAME                     TABLESPACE_NAME                TABLE_TYPE  PCT_THRESHOLD
------------------------------ --------------------------- ------------------------------ ------------------------------ ----------- -------------
PK_ADMIN_DOCINDEX              IOT - TOP                   ADMIN_DOCINDEX                 ADMIN_TBS                      TABLE                  20

SQL> select segment_name,segment_type,tablespace_name from user_segments where SEGMENT_NAME='PK_ADMIN_DOCINDEX';

SEGMENT_NAME                                                                      SEGMENT_TYPE       TABLESPACE_NAME
--------------------------------------------------------------------------------- ------------------ ------------------------------
PK_ADMIN_DOCINDEX                                                                 INDEX              ADMIN_TBS

SQL> 

       最后,关于IOT表的学习下篇继续。

金秋十月:结束繁忙的假期

           金秋十一艳阳天,这个国庆我很忙!

           匆匆的结束了这个“长达”14天的我的国庆节:9月27号从厦门去天津办理护照,28号从天津奔赴郑州,短暂停留之后,29号从郑州直奔信阳老家,动车非常快,310 Km/h,1小时18分就到了,就是两端的车站都是新站,且刚刚投入使用,不过据说始发站郑州东站是目前全亚洲最大的火车站,而信阳东站却稍微有点儿偏。

           29号下午回家之后,甩开膀子就帮老爸开始干活儿、建房子,顺带照顾身体不适的老妈,一直持续到昨天下午。今早(10月10号)出门来武汉,现在天河机场,晚上到厦门,明天开始上班。临走之前,老爹老娘都不舍得他们大儿子走,千叮咛万嘱咐的,呵呵,其实儿子何尝不是也放心不下?

            为了生计,四处奔波。。。

           09年十一,我奔波在重庆至老家的往返途中,为了回家看看老爸老妈;

           10年十一,独自一人乘火车从厦门去昆明、大理散心、看风景,寻找爱情;

           11年十一,带女朋友一起从厦门去北京玩儿;

           12年十一,独自一人奔波在厦门–>杭州–>天津–>郑州–>信阳–>武汉–>厦门。值得欣慰的是,今年十一是我近三年来连续陪同父母在一起时间最长的一个假期。

                                                                                  2012年10月10日 18点54分于武汉天河机场