今天我们介绍在Oralce中用的比较多的两种表:堆组织表和索引组织表
堆组织表
应该用99%的情况下使用的可能都是堆组织表。在调用CREATE TABLE语句的时候默认创建的就是堆组织表。
例如:
CREATE TABLE T {
X INT
y date
z clob
}
堆实际上就是一个很大的空间、磁盘或者内存区,会以一种随机的方式管理。数据会挡在最合适的地方而不是以某种特定的顺序来放置。
在全表扫描的时候,会按命中的顺序来获取数据,而不是以插入的顺序来获取数据。所以如果想要以顺序的方式,需要添加ORDER BY
索引组织表
索引组织表(IOT)就是存储在索引中的表,存在堆中的表时无序的,但是IOT中存储的数据是以主键存储和排序的。
那么什么样的表时索引组织表呢,我们下面来看一个例子:
如果我们创建了一个完全由主键构成的表:
CREATE TABLE keywords{
word varchar2(50),
position int,
doc_id int,
primary key(word,position,doc_id)
}
这张表完全由主键列构成,因此有超过了100%的主键索引开销。表的大小和主键索引大小相当,当我们想使用word或者word和position查询数据的时候,表本身是没有用的,因为我们需要的数据完全在索引中就可以获得了。IOT就相当于一个完全由主键构成的索引表。即没有堆表只有索引的表。如果我们在堆表中按上述方法建立表,那么我们在使用word查询数据的时候还需要通过索引查到的rowid回到堆表中获取数据。而如果我们用IOT就可以直接获取到数据。并且需要的空间也减少一半。
还有一点由于IOT是按照主键的顺序写入到数据库的块中的,所以当我们需要根据主键查找某个区间的数据的时候,有很大的可能可以在同一个块中找到需要的数据加快查询速度。
IOT创建语法以及参数
通过创建一个IOT表只需要:
CREATE TABLE T1 {
X int primary key
y varchar2(25)
z date
}
organization index
需要注意的是由于IOT是根据主键创建的表,所以表中一定要有主键。
和堆表相比IOT没有PCTUSERD但是有PCTFREE,因为索引是一个复杂的数据结构,不是随机存储的,对于给定的组件,他一定会存储到指定的块上,索引不需要PCTUSED来判断这个块是否是空闲的。
除了与堆表相同的参数,IOT表也新增了几个参数:
1、NOCOMPRESS和COMPRESS N
NOCOMPRESS和COMPRESS N是用来表示是否压缩表中的一些重复数据,其中COMPRESS N的N表示呀压缩的列数,如以下例子:
表一:NOCPMPRESS
sys,table,t1 | sys, table,t2 | sys,table,t3 | sys,table,t4 |
---|---|---|---|
sys,table,t5 | sys, table,t6 | sys,table,t7 | sys,table,t8 |
… | … | … | … |
sys,table,t100 | sys, table,t101 | sys,table,t102 | sys,table,t10 |
表二:CPMPRESS 2
sys,table | t1 | t2 | t3 |
---|---|---|---|
t4 | t5 | t6 | t7 |
… | … | … | … |
t100 | t101 | t102 | t103 |
也就是重读的sys和table只出现一次,然后促成能第三列。每个块中可以此存储更多条目,并且不会影响并发性。
2、PCTTHRESHOLD、OVERFLOW、INCLUDING
这三个属性主要目的是让索引的叶子块能高效的存储数据。因为索引块上面的行数会比堆表块中的行数多上几倍,索引指望块能得到多行,否则Oracle会花费大量是hijack来维护索引。因为每个INSERT和UPDATE都有可能导致索引块的分解。
OVERFLOW就运行你使用另一个段,是的IOT成功一个多段对象。如果IOT的行数据太大的话,可以让溢出的参数存储到其他段中,而块中存储指向对应数据的指针。
使用溢出段的条件就由PCTTHRESHOLD和INCLUDING来指定:
PCTTHRESHOLD:行中的数据量超过这个百分比的时候,行中余下的行存储到离别处。如果PCTTHRESHOLD是10%,那么一个8K的块存储超过800字节的行的时候就会把其中一部分存到到别处
INCLUDING:行中从第一列直到INCLUDING字句所指定的列(包含其指定的列)的所有列都存储到索引块上,余下的列存储到溢出段中。