数据区概述
数据扩展(extent)是由一组连续的数据块(data block)构成的数据库逻辑存储分配单位。而段(segment)则是由一个或多个数据扩展构成。当一个段中已有空间已经用完,Oracle为这个段分配新的数据扩展。
数据区何时被分配
当用户创建数据表时,Oracle为此表的数据段分配一个包含若干数据块的初始数据扩展(initial extent)。虽然此时数据表中还没有数据,但是在此初始数据扩展中的数据块已经为插入新数据做好了准备。
如果一个段(segment)的 初始区中的数据块(data block)都已装满,且有新数据插入需要空间时,Oracle自动为这个段分配一个增量数据扩展(incremental extent)。增量数据扩展 是一个段中继已有数据扩展之后分配的后续数据扩展,她的容量大于或等于之前的数据扩展 。
为了管理的需要,每个段的段头(header block)中包含一个记录此段所有数据扩展(extent)的目录。(对于这里的数据扩展目录,个人理解为,在本地管理表空间中段所使用的位图来管理数据区的分配,待验证 )
如何决定分配数据扩展的容量与数量
每个段(segment)的定义中都包含了数据扩展(extent)的存储参数 (storage parameter)。存储参数适用于各种类型的段。这个参数控制着Oracle如何为段分配可用空间。例如,用户可以在 CREATE TABLE 语句中使用 STORAGE 子句设定存储参数,决定创建表时为其数据段(data segment)分配多少初始空间,或限定一个表最多可以包含多少数据扩展。如果用户没有为表设定存储参数,那么表在创建时使用所在表空间(tablespace)的默认存储参数。
用户既可以使用 数据字典管理的表空间(dictionary managed tablespace)(依赖数据字典表监控空间的利用情况),也可以使用本地管理的表空间(locally managed tablespace)(使用位图(bitmap)来标记可用与已用空间)。由于本地管理的表空间性能较好且易于管理,当用户没有显式地设定数据扩展(extent)管理参数时,除了10G以后 SYSTEM 之外的所有永久表空间(permanent tablespace)默认使用本地管理方式。
在一个本地管理的表空间中,其中所分配的数据扩展(extent)的容量既可以是用户设定的固定值,也可以是由系统自动决定的可变值。当用户创建表空间(tablespace)时可以使用UNIFORM (用户指定)或 AUTOALLOCATE ( 由系统管理)子句设定数据扩展的分配方式。
对于固定容量(UNIFORM )的数据扩展,用户可以为数据扩展设定容量或使用默认大小(1 MB)。 用户须确保 其中最小的UNIFORM SIZE容量至少能包含5个数据块 。本地管理的临时表空间 在分配数据扩展时只能使用此种方式。
对于由系统管理(AUTOALLOCATE )的数据扩展,由Oracle决定新增数据扩展的最佳容量,其最小容量为 64 KB 。如果创建表空间时使用了“segment space management auto”子句,且数据块容量大于等于 16 KB,Oracle扩展一个段时所创建的数据扩展的最小容量为 1 MB。对于永久表空间上述参数均为默认值。
在本地管理的表空间中,INITIAL ,NEXT ,PCTINCREASE ,和 MINEXTENTS 这四个存储参数可以作用于段(segment),但不能作用于表空间。INITIAL ,NEXT ,PCTINCREASE ,和 MINEXTENTS 相结合可以用于计算段的初始容量。当段容量确定后,Oracle使用内部算法确定其中每个初始数据扩展(extent)的容量。
区如何被分配
Oracle依据表空间管理方式的不同(本地管理(locally managed)或数据字典管理(dictionary managed)),选择不同的算法分配数据扩展(extent)。
对于本地管理的表空间,Oracle在为新的数据扩展(extent)寻找可用空间时,首先选择一个属于此表空间的数据文件(datafile),再搜 索此数据文件的位图(bitmap)查找连续的数据块(free block)。如果此数据块中没有足够的连续可用空间,Oracle将查询其他数据文件。
数据区合适被回收
Oracle 数据库提供了 Segment Advisor 工具,她依据方案对象(schema object)存储空间中的碎片程度来判断此对象中是否包含可回收的空间。
一般来说,在用户将一个段(segment)对应的方案对象(schema object)移除(使用 DROP TABLE 或 DROP CLUSTER 语句)之前,此段的数据扩展(extent)不会被回收到表空间(tablespace)中,但是以下情况例外:
1、表,簇表的所有者(owner)或拥有 DELETE ANY 权限的用户, 可以使用 TRUNCATE...DROP STORAGE 语句将表,簇表的数据清除
2、DBA 可以使用以下语法收回一个段中未使用的数据扩展:
ALTER TABLE table_name DEALLOCATE UNUSED;
3、如果用户为回滚段(rollback segment)设定了 OPTIMAL 参数,Oracle将周期性地从其中回收数据扩展。
当数据扩展(extent)被释放后,Oracle修改数据文件中的位图(对于本地管理的表空间)或更新数据字典(对于数据字典管理的表空间),将回收的数据扩展视为可用空间。被释放的数据扩展中的数据无法继续访问。
非簇表中的数据扩展
只要用户没有移除(drop)或清空(truncate)非簇表,那么对应数据段内的任何数据块都不会被回收。Oracle会在插入数据时使用这些数据块(只要数据块有足够的空间)。即使用户删除(delete)了表的所有行,Oracle也不会回收此表的数据块供表空间内的其他方案对象(schema object)使用。
当用户移除(drop)了一个非簇表(nonclustered table),Oracle将在需要空间时回收此表对应的数据扩展 。Oracle将此表对应的数据段(data segment)、索引段(index segment)中包含的数据扩展(extent)全部收回,并供存储于此表空间的其他方案对象(schema object)使用。
对于数据字典管理的表空间(dictionary managed tablespace),当一个段(segment)需要的数据扩展(extent)比现有可用扩展的都大时,Oracle通过寻找、合并连续的被回收的数据扩展来形成更大的数据扩展。这个过程被称为数据扩展合并 (coalescing)。本地管理的表空间没有必要进行数据扩展合并,因为所有连续空间都可以被用于分配新数据扩展,而无需关心所用空间是如何被回收的。
簇表中的数据扩展
Therefore, if you drop one table in a cluster, the data segment remains for the other tables in the cluster, and no extents are deallocated. You can also truncate clusters (except for hash clusters) to free extents.
簇表(clustered table)的数据存储在为整个簇(cluster)分配的数据段(data segment)中。因此当用户移除(drop)簇中的一个表时,数据段还要为簇中的其他表保留,因此没有数据扩展(extent)被回收。用户可以通过清空(truncate)整个簇来回收属于簇的数据扩展(哈希簇(hash cluster)除外)。
物化视图的数据扩展
Oracle回收属于物化视图(materialized view)及其日志(materialized view log)的数据扩展的方式与表或簇相同。
索引的数据扩展
只要索引存在,那么对应索引段(index segment)的所有数据扩展(extent)都不会被回收。当用户移除(drop)索引或相关的表、簇表时,Oracle才将索引使用的数据扩展回收。
临时段中的数据扩展
当Oracle执行完一个 SQL 语句,且在执行过程中使用的临时段时,Oracle通过以下机制对临时段的数据空间进行回收。
1、当用户执行单一排序语句时,Oracle将在此用户的临时表空间中创建为这个排序服务的临时段,并在执行后将此临时段使用的数据扩展回收。
2、 当用户执行 多重排序 语句 时 ,可能会使用临时表空间中专为排序而创建的排序段。在每个实例中只会分配一个排序段,在排序操作使用后也不会被回收,而是继续供以后的多重排序使用。
同一会话或同一事务的多个 SQL 语句,有可能共同使用一个临时表的临时段存储临时数据。在这种情况下,Oracle在会话或事务结束后才移除临时段,并为临时段所在表空间回收使用的数据扩展。
回滚段的数据扩展
如果用户为回滚段(rollback segment)设定了 OPTIMAL 参数, Oracle周期性地检查数据库回滚段的容量是否超过了最优值。如果回滚段超过了这个最优值(即回滚段中的数据扩展过多),Oracle将自动地从回滚段回收一些数据扩展。