在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表的学习下篇继续。