Oracle中主要有9种表类型:
1)堆组织表(heap organized table)
这就是标准数据库表。数据以堆的方式管理。增加数据时,会使用段中找到的第一个能放下此数据的自由空间。从表中删除数据后,允许以后的INSERT和UPDATE重用这部分空间。堆(heap)是一组空间,以一种随机的方式使
用。
2)索引组织表(index organized table)
表按索引结构存储。这就强制要求行本身有某种物理顺序。在堆组织表中,数据可以放在任何位置;而在IOT中,数据要根据主键有序地存储。
3)索引聚簇表(index clustered table)
聚簇(cluster)是指一个或多个表组成的组,这些表物理地存储在相同的数据库块上,有相同聚簇键值的所有行会相邻地物理存储。
首先,多个表可以物理地存储在一起。一般而言,你可以认为一个数据库块上存储一个表的数据,但是对于聚簇表,可能把多个表的数据存储在同一个块上。
其次,包含相同聚簇键值(如DEPTNO=10)的所有数据会物理地存储在一起。这些数据按聚簇键值“聚簇”在一起。聚簇键使用B*树索引建立。
4)散列聚簇表(hash clustered table)
类似于索引聚簇表,但是不使用B*树索引聚簇键来定位数据,而是通过散列聚簇键将数据散列到数据库块上。在散列聚簇中,数据就是索引(这是隐喻的说法)。如果需要频繁地通过键的相等性比较来读取数据,散
列聚簇表就很适用。
5)有序散列聚簇表(sorted hash clustered table)
Oracle 10g中新增,它具有散列聚簇表的特性,同时兼有IOT的一些特性。
行按某个键值(如CUSTOMER_ID)散列,而与该键相关的一系列记录按照插入顺序存储。(因此这些记录可能是是基于时间戳的记录)。
例如,订单输入系统中,订单会按先进先出(FIFO)的方式获取和处理。在这样一个系统中,有序散列聚簇就是适用的数据结构。
6)嵌套表(nested table)
嵌套表是Oracle对象关系扩展的一部分。它们实际上就是系统生成和维护的父/子关系中的子表。
7)临时表(temporary table)
临时表要根据需要从当前用户的临时表空间分配临时区段。每个会话只能看到这个会话分配的区段;它从不会看到其他任何会话中创建的任何数据。
8)对象表(object table)
对象表基于某种对象类型创建。它们拥有非对象表所没有的特殊属性,如系统会为对象表的每一行生成REF(对象标识符)。
对象表实际上是堆组织表、索引组织表和临时表的特例,还可以包含嵌套表作为其结构的一部分。
9)外部表(external table)
这些表并不存储在数据库本身中,而是放在数据库之外,即放在平常的操作系统文件中。
利用外部表可以查询数据库之外的一个文件,就好像这个文件也是数据库中平常的表一样。外部表对于向数据库加载数据最有用(外部表是非常强大的数据加载工具)。
Oracle
10g更进一步,还引入了一个外部表卸载功能,在不使用数据库链接的情况下,这为在Oracle数据库之间移动数据提供了一种简单的方法。
二、段
段就是占用存储空间的数据库对象,占用存储空间的每一个对象最后都会存储在一个段中,如表、索引、回滚段等。
段的类型
1)表段
2)表分区段(table partition)或子分区段(subpartition)
这种段类型用于分区,与表段很相似。分区表由一个或多个分区段(table partition
segment)组成,组合分区表则由一个或多个表子分区段(tablesubpartition segment)组成。
3)聚簇段(cluster)
“聚簇”是指这个段能把相关的信息物理的聚在一起。有两种类型的聚簇:B*树聚簇和散列聚簇。
4)索引段(index)
5)索引分区(index partition)
类似与表分区,这种段类型包含一个索引的某个片。分区索引由一个或多个索引分区段(index partition
segment)组成。
6)lob段(lobsegment),lob索引段(lobindex),Lob分区段(lob
partition)、lob子分区段(lob subpartition)
用于保存大对象 (large object或LOB)。
7)嵌套表段(nested table)
为嵌套表指定的段类型。
8)回滚段(rollback)和Type2 undo段
undo数据就存储在这里。回滚段是DBA手动创建的段。Type2 undo段由Oracle自动创建和管理。
创建表时,会创建一个表段。创建分区表时,则每个分区会创建一个段。创建索引时,就会创建一个索引段,依此类推。
例如 create table t( x int primary key, y clob)
这样一个简单的语句就会创建4个段:
一个是TABLE T的表段;
一个是索引段(这个索引是为支持主键而创建的);
另外还有两个CLOB段(一个是LOB 索引,另一个段是LOB数据本身)。
11g
Release2之后,默认情况下,段会延迟到插入第一行数据之后才创建。也可以用下面语句在创建表格同时就创建段。
create table t( x int primary key, y clob) segment creation
immediate;
三、段空间管理
段空间管理是从段的表空间(而且段从不会跨表空间)继承来的一个属性。使用CREATE
TABLESPACE语句创建一个本地管理的表空间时,可以使用 SEGMENT SPACE MANAGEMENT
子句来设定段内的可用/已用空间如何管理。
1)手动段空间管理(Manual Segment Space Management,MSSM)
Oracle 使用可用块列表(free
list)来管理段内的可用空间。可用块列表记录了所有可以被用于插入新数据的数据块。
2)自动段空间管理(Automatic Segment Space
Management,ASSM)
Oracle
使用位图(bitmap)管理段内的可用空间。[注意此处的位图与本地管理的表空间使用的位图不一样]此处的位图用于描述段内每个数据块是否有足够的可用空间来插入新数据。随着一个数据块中可用空间的变化,她的状态也被及时地反映到位图中。Oracle
使用位图可以更自动化地管理段内的可用空间。
应用于ASSM的存储设置参数只有:
· BUFFER_POOL
· PCTFREE
· INITRANS和MAXTRANS
创建段时也可以接受其他参数,但是这些参数将被忽略。
1、高水位线
在段中有一个高水位线(high-water
mark,HWM)。如果把段想象成从下到上的一系列的块,HWM代表包含了数据的最上面的块。
HWM首先位于新创建表的第一个块中。在这个表中插入数据后,HWM会升高。如果我们删除了表中的一些(甚至全部)行,HWM也不会降低。这样就可能会有许多块不再包含数据,但是它们仍在HWM之下,直到重建、截除(TRUNCATE)或收缩这个段。
(段收缩是Oracle 10g的一个新特性,只有当段在一个ASSM表空间中时才支持这个特性,通过下述语句
alter table t enable row movement; alter table t shrink
space;
可以在一个表格上执行段收缩)
因为Oracle在全面扫描段时会扫描HWM之下的所有块,即使其中不包含任何数据,这会影响全面扫描的性能,特别是当HWM之下的大多数块都为空时。所以删除表中所有行的时候,如果可能就使用TRUNCATE。
在ASSM表空间中,除了一个HWM外,还有一个低HWM。在MSSM中,HWM推进时
(例如,插入行时。段分配空间时以区段(extent)为单位,一个区段包括很多物理连续的块),所有块都会被格式化并立即有效,Oracle可以安全地读取这些块。不过,对于ASSM,HWM推进时,Oracle并不会立即格式化所有块,只有在第一次向这些块插入记录时才会完成格式化,以便安全地读取。对于ASSM,数据可能插入到高水位和低水位之间的任意块,因此这个区域中的很多块都不会被格式化。全面扫描时,需要知道读取的块是否未格式化,为了避免段中每个块都要做检查,Oracle对低水位以下的所有块都会直接读取,低水位和高水位之间的块则需要参考ASSM的块位图信息来查看哪些块应该读取,哪些应该忽略。
2、FREELIST
使用MSSM时,Oracle会在FREELIST中维护HWM以下,可供用来插入数据的块。如果预计到会有多个并发用户在一个对象上执行大量的INSERT或UPDATE活动,就可以配置多个FREELIST,这对性能提升很有好处。
3、PCTFREE和PCTUSED
PCTFREE参数用来告诉Oracle应该在块上保留多少空间来完成将来的更新。默认情况下,这个值是10%。如果未用空间的百分比高于PCTFREE中的指定值,这个块就认为是“可用”,可以用来插入数据。
PCTUSED则告诉Oracle当前已经变成“不可用”的一个块上未用空间百分比需要达到多大(由于删除,更新等释放了空间)才能使它再次变为"可用"的。默认值是40%。
使用MSSM时,这2个参数控制着块何时放入FREELIST中,以及何时从FREELIST中取出。如果使用默认值:
PCTFREE为10,PCTUSED为40,那么在块到达90%满之前(有10%以上的自由空间),这个块会一直在FREELIST
上。一旦到达90%满,就会从FREELIST中取出,而且直到块上的自由空间超过了块的60%时,才会重新回到FREELIST上。
使用ASSM时,PCTFREE仍然会限制能否将一个新行插入到一个块中,但是PCTUSED将被忽略。
PCTFREE设置太大,则会浪费空间;设置太小,更新行时就会导致行迁移。
4、行迁移
行迁移(row
migration)是指由于某一行变得太大,导致块中已经放不下这一行,Oracle
将此行数据迁移(migrate)到新的数据块中,在被迁移数据行原来所在位置保存一个指向新数据块的指针。被迁移数据行的ROWID保持不变。行迁移会影响性能,必须执行更多的I/O才能得到行数据。
5、行链接
行链接(row
chaining)发生在插入数据时,如果一个block不能存放下一行记录,Oracle将使用链接多个block存储这一行记录,如果行比较大,容易发生。
可以使用analyze table xxx list chained rows
命令来分析表格中的行链接或者行迁移。
为此需要先建立chained_rows表格。
首先执行$ORACLE_HOME/RDBMS/ADMIN/utlchain.sql脚本建立chained_rows表格,
然后执行analyze table xxx list chained rows [into
chained_rows],
如果存在行链接或者行迁移,查询chained_rows就能找到发生了行链接或者行迁移的行。