1、 段
Oracle中的段是占用磁盘物理空间的一个对象。尽管有多种段类型,常见的段类型如下:
u 聚簇(cluster)
这种段类型能存储表。有两种类型的聚簇:B*树聚簇和散列聚簇。聚簇通常用于存储多个表上的相关数据,将其“预连接”存储到同一个数据库块上;还可以用于存储一个表的相关信息。
u 表(table)
表段保存一个数据库表的数据,这可能是最常用的段类型,通常与索引段联合使用。
u 表分区(table partition)或子分区(subpartition)
这种段类型用于分区,与表段很相似。分区表由一个或多个表分区段组成,组合分区表则由一个或多个表子分区段组成。
u 索引(index)
这种段类型可以保存索引结构。
u 索引分区(index partition)
类似于表分区,这种段类型包含一个索引的某个片。分区索引由一个或多个索引分区段组成。
u lob分区(lob partition)、lob子分区(lob subpartition)、lob索引(lobindex)和lob段(lobsegment)
lobindex和lobsegment段保存大对象的结构。对包含LOB的表分区时,lobsegment也会分区,lob分区段正是用于此。并没有一种lobindex分区段类型,不论是出于什么原因,Oracle将分区lobindex标记为一个索引分区。
u 嵌套表(nested table)
这是为嵌套表指定的段类型,它是主/明细关系中一种特殊类型的“子”表。
u 回滚段(rollback)和Type2 undo段
undo数据就存在这里。回滚段是DBA手动创建的段。Type2 undo段由Oracle自动创建和管理。
最常见的情况是,表是一个段,索引也是一个段。创建一个表时,通常就在创建一个新的表段。这个段包含extent,extent包含block。这是存储层次结构。考虑如下create table语句:
从查询结果中可以看到,表本身创建了一个段;主键约束创建了一个索引段。另外,每个LOB对象分别创建了两个段。一个段用于存储字符大对象或二进制大对象所指的实际数据块,另一个段用于“组织”这些数据块。
2、 段空间管理
从9i开始,管理段空间有两种方法:
u 手动段空间管理(Manual Segment Space Management):由你设置FREELISTS、FREELIST GROUPS、PCTUSERD和其他参数来控制如何分配、使用和重用段中的空间。为了方便起见,将手动段空间管理简写为MSSM。
u 自动段空间管理(Automatic Segment Space Management,ASSM):你只需要控制与空间使用相关的一个参数:PCTFREE。创建段时可以接受其他参数,但是会被Oracle忽略。
MSSM是Oracle的遗留实现,由于使用MSSM时要设置数不胜数的参数,并且需要对这些参数进行调整,人们并不希望如此麻烦,这便催生了ASSM的出现。
3、 高水位线(high-water mark,HWM)
高水位线是一个很有趣的概念,但是也是一个非常重要的概念。顾名思义,高水位线有点类型于水文监测站里测水深的标杆一样,当水涨的时候,水位线随之上升,并在标杆留下一个水印痕,这个水印痕就是高水位线。但当水位降落的时候,当前水位也会在标杆上留下一个水印痕,这个并不是高水位线,学名叫低HWM。稍后会介绍。
其实在数据库中,上述比喻很相似。如果把表想象成一个平面结构,或者想象成从左到右依次排开的一系列块,高水位线就是包含了数据的最右边的块。如下图所示。
当表刚创建时,HWM位于表的第一个块中。过一段时间后,随着在这个表中放入数据,而且使用了越来越多的块,HWM会升高。但当我们删除了表中的一些(甚至全部)行,可能就会出现许多块不再包含数据,但仍然处于HWM之下,而且会一直保持在HWM之下。记住:HWM永远不会下降,除非使用rebuild、truncated或shrunk这个对象(shrinking是10g的一个新特性,仅ASSM支持)。
HWM很重要,因为Oracle在全表扫描时会扫描HWM之下的所有块,即使其中不包括任何数据。这会影响full scan的性能,特别是当HWM之下的绝大多数块都为空时。下面来看一个例子,创建一个有1000000行的表,然后对其执行select count(*)。接着delete所有行,再执行select count(*)统计出0行,比较两次执行的时间。
建表:
插入数据:
删除前(后):
从执行结果中很容易就能看出,删除后的select count(*)反而花费更多的时间,这是为什么呢?这是因为Oracle忙于读取HWM之下的所有块,查看其中是否包含数据。还可能会执行块清除,所以时间会更长。如果使用truncate命令,结果同样很雷人,见下图。
这是因为truncate会把表的HWM重置为0,还会截取表上的相关索引。所以会如此迅速。
在一个MSSM的表空间中,段只有一个HWM。但在ASSM表空间中,除了一个HWM外,还有一个低HWM(上面已提到过)。在MSSM中,HWM推进时(如插入),所有块都会格式化并立即有效,Oracle可以安全的读取这些块。但在ASSM中,HWM推进时,Oracle并不会立即格式化所有块,只是在第一次使用这些块时才会完全格式化,以便安全读取。所以,全表扫描时,并需知道要读取的块是否安全或是否未格式化。为了避免每一个块都必须进行这种安全/不安全检查,Oracle同时维护了一个低HWM和一个HWM。Oracle会全表扫描至HWM,对于低HWM以下的所有块会直接读取并处理,对介于低HWM和HWM之间的块,则必须格外小心,需要参考管理这些块的ASSM位图信息来查看应该读取哪些块,而哪些块则应该忽略。