表类型:
1堆组织表(heap organized table):这些就是“普通”的标准数据库表。数据以堆的方式管理。堆(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)散列,而与该键相关的一系列记录以某种有序顺序到达(因此这些记录是基于时间戳的记录),并按这种有序顺序处理。
例如,客户在你的订单输入系统中下订单,这些订单会按先进先出(first in, first out, FIFO)的方式获取和处理。在这样一个系统中,有序散列聚簇就是适用的数据结构。
6嵌套表(nested table):嵌套表是Oracle对象关系扩展的一部分。它们实际上就是系统生成和维护的父/子关系中的子表。
嵌套表与子表的主要区别是:嵌套表不像子表(如EMP)那样是“独立”表。
7临时表(temporary table):这些表存储的是事务期间或会话期间的“草稿”数据。
临时表要根据需要从当前用户的临时表空间分配临时区段。每个会话只能看到这个会话分配的区段;它从不会看到其他任何会话中创建的任何数据。
8对象表(object table):对象表基于某种对象类型创建。
它们拥有非对象表所没有的特殊属性,如系统会为对象表的每一行生成REF(对象标识符)。
对象表实际上是堆组织表、索引组织表和临时表的特例,还可以包含嵌套表作为其结构的一部分。
9外部表(external table):这些表并不存储在数据库本身中,而是放在数据库之外,即放在平常的操作系统文件中。
在Oracle9i及以上版本中,利用外部表可以查询数据库之外的一个文件,就好像这个文件也是数据库中平常的表一样。
外部表对于向数据库加载数据最有用(外部表是非常强大的数据加载工具)。Oracle 10g则更进一步,还引入了一个外部表卸载功能,在不使用数据库链接的情况下,这为在Oracle数据库之间移动数据提供了一种简单的方法。
表的一般性
1.一个表最多可以有1000列,Oracle在内部会把列数大于254的行存储在多个单独的行段(row piece)中,这些行段相互指向,而且必须重新组装为完整的行影像。
2.表的行数几乎是无限的,一般来讲,一个表空间最多有1022个文件.
3.表中的列有多少种排列(以及这些列的函数有多少种排列),表就可以有多少个索引。
4.即使在一个数据库中也可以有无限多个表。
段的含义:段(segment)是占用磁盘上存储空间的一个对象。
段的类型:
1聚簇(cluster):这种段类型能存储表。
有两种类型的聚簇:B*树聚簇和散列聚簇。
聚簇通常用于存储多个表上的相关数据,将其“预联结”存储到同一个数据库块上;还可以用于存储一个表的相关信息。
“聚簇”这个词是指这个段能把相关的信息物理的聚在一起。
2表(table):表段保存一个数据库表的数据,这可能是最常用的段类型,通常与索引段联合使用。
3表分区(table partition)或子分区(subpartition):这种段类型用于分区,与表段很相似。
分区表由一个或多个分区段(table partition segment)组成,组合分区表则由一个或多个表子分区段(table subpartition segment)组成。
4索引(index):这种段类型可以保存索引结构。
5索引分区(index partition):类似与表分区,这种段类型包含一个索引的某个片。分区索引由一个或多个索引分区段(index partition segment)组成。
6Lob分区(lob partition)、lob子分区(lob subpartition)、lob索引(lobindex)和lob段(lobsegment):lobindex和lobsegment段保存大对象(large object或LOB)的结构。
对包含LOB的表分区时,lobsegment也会分区,lob分区段(lob partition segment)正是用于此。
没有一种lobindex分区段。Oracle将分区lobindex标记为一个索引分区。
7嵌套表(nested table):这是为嵌套表指定的段类型,它是主/明细关系中一种特殊类型的“子”表。
8回滚段(rollback)和Type2 undo段:undo数据就存储在这里。回滚段是DBA手动创建的段。Type2 undo段由Oracle自动创建和管理。
示例:
1查看段select segment_name, segment_type from user_segments;有0行信息。
2创建表Create table t ( x int primary key, y clob, z blob );
3再次查看有6行信息。分别是:LOBINDEX,LOBSEGMENT,INDEX,LOBINDEX,LOBSEGMENT,TABLE
段空间管理
手动段空间管理(Manual Segment Space Management):由你设置FREELISTS、FREELIST GROUPS、PCTUSED和其他参数来控制如何分配、使用和重用段中的空间。
自动段空间管理(Automatic Segment Space Management, ASSM):你只需控制与空间使用相关的一个参数:PCTFREE。
高水位线(high-water mark,HWM)
如果把表想象成一个“平面”结构,或者想象成从左到右依次排开的一系列块,高水平线(high-water mark,HWM)就是包含了数据的最右边的块。
HWM首先位于新创建表的第一个块中。过一段时间后,随着在这个表中放入数据,而且使用了越来越多的块,HWM会升高。
如果我们删除了表中的一些(甚至全部)行,可能就会有许多块不再包含数据,但是它们仍在HWM之下,而且这些块会一直保持在HWM之下,直到重建、截除或收缩这个对象
(将段收缩是Oracle 10g的一个新特性,只有当段在一个ASSM表空间中时才支持这个特性)。
在select count(*)有1000000记录表时花费的时间和delete全部表记录后select count(*)花费的时间一样长。所以如果要删除全部记录,最好使用truncate,TRUNCATE会把表的HWM重置回“0”,还会截除表上的相关索引。
在MSSM中只有HWM,但是在ASSM中除了HWM还有低HWM,
自由列表(freelist)
自由列表(freelist)中为有自由空间的对象维护HWM一些的块。在ASSM表空间中根本就没有;仅MSSM表空间使用这个技术。
例子:
create table t ( x int, y char(50) ) storage( freelists 5 ) tablespace MSSM;创建配置有5个freelists的表
alter table t storage ( FREELISTS 5 );修改配置
PCTFREE和PCTUSED
一般而言,PCTFREE参数用来告诉Oracle应该在块上保留多少空间来完成将来的更新。默认情况下,这个值是10%。如果自由空间的百分比高于PCTFREE中的指定值,这个块就认为是“自由的”。
PCTUSED则告诉Oracle当前不“自由”的一个块上自由空间百分比需要达到多大才能使它再次变为自由的。默认值是40%。
使用MSSM时,PCTUSED和PCTFREE都很重要;对于ASSM,只有PCTFREE是重要的。
一方面,你要使用这些参数来避免迁移过多的行。
另一方面,要使用这些参数避免浪费太多的空间。
INITRANS和MAXTRANS
段中每个块都有一个块首部。这个块首部中有一个事务表。事务表中会建立一些条目来描述哪些事务将块上的哪些行/元素锁定。这个事务表的初始大小由对象的INITRANS设置指定。
对于表,这个值默认为2(索引的INITRANS也默认为2)。
事务表会根据需要动态扩展,最大达到MAXTRANS个条目(假设块上有足够的自由空间)。所分配的每个事务条目需要占用块首部中的23~24字节的存储空间。
注意,对于Oracle 10g,MAXTRANS则会忽略,所有段的MAXTRANS都是255。
1堆组织表:
执行CREATE TABLE语句时,默认得到的表类型就是堆组织表。
堆(heap)是计算机科学领域中得到深入研究的一种经典数据结构。
它实际上就是一个很大的空间、磁盘或内存区(当然,这里所说的磁盘是指数据库表的相应磁盘),会以一种显然随机的方式管理。
数据会放在最合适的地方,而不是以某种特定顺序来放置。
堆组织表的选项:
FREELISTS:仅适用于MSSM。每个表都会在一个freelist上管理堆中分配的块。一个表可以有多个freelist。如果你认定会有多个并发用户对表执行大量的插入,配置多个freelist可能会大大地改善性能(可能要以额外的存储空间为代价)。
PCTFREE:ASSM和MSSM都适用。在INSERT过程中,会测量块的充满程度。
根据块当前充满的程度,这个参数用于控制能否将一行增加到一个块上。这个选项还可以控制因后续更新所导致的行迁移,要根据将如何使用表来适当地设置。
PCTUSED:仅适用于MSSM。度量一个块必须为多空才允许再次插入行。如果块中已用的空间小于PCTUSED,就可以插入新行了。
INITRANS:ASSM和MSSM都适合。为块初始分配的事务槽数。如果这个选项设置得太低(默认值为2,这也是最小值),可能导致多个用户访问的一个块上出现并发问题。
如果一个数据块机会已满,而且事务表无法动态扩展,会话就会排队等待这个块,因为每个并发事务都需要一个事务槽。
如果你认为会对同样的块完成多个并发更新,就应该考虑增大这个值。
技巧示例:了解一个给定表的CREATE TABLE语句中主要有哪些可用的选项。
首先,尽可能简单地创建表:
create table t ( x int primary key, y date, z clob);
然后,使用标准内置包DBMS_METADATA,查询这个表的定义
select dbms_metadata.get_ddl( 'TABLE', 'T' ) from dual;
2索引组织表
索引组织表(index organized table,IOT)就是存储在一个索引结构中的表。
存储在堆中的表是无组织的,IOT中的数据则按主键存储和排序。
使用堆组织表时,我们必须为表和表主键上的索引分别留出空间。
而IOT则不存在主键的空间开销,因为索引就是数据,数据就是索引,两者已经合二为一。
创建索引组织表:
create table iot ( x int, y date, z varchar2(2000),
constraint iot_pk primary key (x) ) organization index pctthreshold 10 overflow;
参数:
NOCOMPRESS它告诉Oracle把每个值分别存储在各个索引条目中(也就是不压缩)。如果对象的主键在A、B和C列上,A、B和C的每一次出现都会物理地存储。
相反COMPRESS N,N是一个整数,表示要压缩的列数。这样可以避免重复值,并在块级提取“公因子”(factor out)。这样在A的值(以及B的值)重复出现时,将不再物理地存储它们。
OVERFLOW:子句允许你建立另一个段,如果IOT的行数据变得太大,就可以溢出到这个段中。
PCTTHRESHOLD:行中的数据量超过块的这个百分比时,行中余下的列将存储在溢出段中。
INCLUDING:行中从第一列直到INCLUDING子句所指定列(也包括这一列)的所有列都存储在索引块上,余下的列存储在溢出段中。
3索引聚簇表
聚簇(cluster)是指:如果一组表有一些共同的列,则将这样一组表存储在相同的数据库块中;聚簇还表示把相关的数据存储在同一个块上。
示例:
创建一个聚簇对象
create cluster emp_dept_cluster (deptno number(2) )size 1024;
创建聚簇键索引
create index emp_dept_cluster_idx on cluster emp_dept_cluster;
创建表
create table dept(deptno number(2) primary key,dname varchar2(14),
loc varchar2(13)) cluster emp_dept_cluster(deptno);
4散列聚簇表
与索引聚簇类似,聚簇键索引被一个散列函数所取代。表中的数据就是索引;
创建散列聚簇:
create cluster hash_cluster( hash_key number )hashkeys 1000 size 8192 tablespace mssm;
5有序散列聚簇表
有序散列聚簇是Oracle 10g中新增的。其中不仅有前面所述的散列聚簇的有关性质,还结合了IOT的一些性质。
创建有序散列聚簇:
CREATE CLUSTER shc (cust_id NUMBER,
order_dt timestamp SORT)
HASHKEYS 10000
HASH IS cust_id
SIZE 8192
6嵌套表
语法
创建两个表:
create table dept(deptno number(2) primary key,dname varchar2(14),loc varchar2(13));
create table emp
(empno number(4) primary key,
ename varchar2(10),
job varchar2(9),
mgr number(4) references emp,
hiredate date,
sal number(7, 2),
comm number(7, 2),
deptno number(2) references dept);
创建对应的等价实现和嵌套表类型:
create or replace type emp_type
as object
(empno number(4),
ename varchar2(10),
job varchar2(9),
mgr number(4),
hiredate date,
sal number(7, 2),
comm number(7, 2));
create or replace type emp_tab_type as table of emp_type;
创建嵌套表
create table dept_and_emp
(deptno number(2) primary key,
dname varchar2(14),
loc varchar2(13),
emps emp_tab_type )
nested table emps store as emps_nt;
CREATE TABLE包括列EMPS(类型为EMP_TAB_TYPE),和相应的NESTED TABLE EMPS STORE AS EMPS_NT。这样除了表DEPT_AND_EMP之外,还会创建一个真正的物理表EMPS_NT,这个表与DEPT_AND_EMP是分开的。
alter table emps_nt add constraint emps_empno_unique unique(empno)
7临时表
临时表(Temporary table)用于保存事务或会话期间的中间结果集。
create global temporary table temp_table_session on commit preserve rows as select * from scott.emp where 1=0;
ON COMMIT PRESERVE ROWS子句使得这是一个基于会话的临时表。
8对象表
对象表(object table)是基于一个TYPE创建的表,而不是作为一个列集合。
示例:
创建类型:
create or replace type address_type as object
( city varchar2(30),
street varchar2(30),
state varchar2(2),
zip number)
create or replace type person_type as object
( name varchar2(30),
dob date,
home_address address_type,
work_address address_type)
创建表:
create table people of person_type;
插入值:
insert into people values ( 'Tom', '15-mar-1965',
address_type( 'Reston', '123 Main Street', 'Va', '45678' ),
address_type( 'Redwood', '1 Oracle Way', 'Ca', '23456' ) );