玖叶教程网

前端编程开发入门

Oracle 逻辑结构篇 之逻辑结构(三)段和区

三、段

在数据库中包含了,每个表空间物理上对应着磁盘上的一个或多个数据文件DATAFILE),一个数据文件只能属于一个表空间。每个表空间又有多个段(SEGMENT组成。

(一)、段类型

当建立数据对象(表、索引、簇等)时,Oracle 会自动给这些数据对象分配相应的存储空间,以存放它们的数据信息,这些为数据对象所分配的存储空间被称为段。一个段只能存放在一个表空间上,但是可分布在属于这个表空间中的多个数据文件中。段是由一个或多个区组成的,段的大小是该段所有区大小总和。在 Oracle 数据库中,每个段只属于一个特定的数据库对象(表、索引等),在这个段中至少包含一个区(初始区)。每种数据对象都具有相应的段,Oracle 提供了以下一些段类型:

1)表段(Table):

表是在数据库内存储数据的最常用方法。表段用于存储常规表(非集簇且未分区)的的数据。表段中的所有数据都必须存储在一个表空间内。例如,当在 USERS_DATA 表空上建立表 S_EMP 时,Oracle 会建立名称为 S_EMP 的表段,并且将该表的所有数据存放在USERS_DATA 表空间上。如果表中有 LOB 列或 VARRAY 列,那么该表不会将这些数据列存储在同一个段。

2)表分区段(Table Partition):

表分区主要用于数据仓库应用。当表中包含大量数据且表的并发使用率很高时,可以把一张大表数据划分成几个小的分区,其中每个分区对应于一个段,这种段类型被称为表分段,并且每个表分区段可以存放到不同表空间上。使用表分区可以降低 I/O 次数,提高 /O 性能。表分区后,每个分区都是一个段,可以指定存储参数单独对它们进行控制。假定一张销售表年数据总量达到 10GB,每个季度平均 2.5GB,如果使用普通表存储数据,那么0GB 数据会存放到一个表段中,那么在统计一季度销售数据时需要扫描 10GB 数据;而如果使用表分区段,那么可以将一、二、三、四季度数据分别存放到不同表分区段中,此时统计一季度销售数据只需要扫描 2.5GB 数据。显然,使用表分区段可以大大降低 I/O 次数并提高 I/O 性能。

注意:使用这种类型的段需要在 Oracle9i 企业版内选择分区(Partitioning) 组件

3)簇段(Cluster):

簇与表一样,是一种数据段类型。簇内的行是基于键值存储的,一个簇可以包含一个或多个表,一个簇内所有的表属于同一个段,并且区和块的存储管理方式也完全相同。例如,如果经常要执行主从表之间的连接查询,那么可以将这两张表的数据组织到簇中。簇段的名称与簇名完全相同。注意,当将表放到簇中时,表的数据存放在簇段中,而不会为该表建立专门的表段。假定在 USERS 表空间上建立簇 ORD_ITEM_CLU,并且将表 ORD 和 ITEM 组织到该簇中,此时只会建立簇段 ORD_ITEM_CLU,而不会建立表段 ORD 和 ITEM。

4)索引段(Index):

索引是用于加快查询速度的数据库对象。当建立索引时,Oracle 会为该索引建立相应的索引段,索引段的名称与索引名完全相同,并且一个索引段只能存放在一个表空间中。如果一个表有三个索引,则使用三个索引段。使用索引段的目的是根据指定的关键字来查找行在表内的位置。例如,当在 EMP 表的 EMPNO 列上建立索引 PK_EMP 时,Oracle 会自动建立索引段 PK_EMP。

5)按索引组织的表段(Index-organized table):

一般情况下,表与索引数据分别存放在表段和索引段中。例如,表 EMP 及其索引PK_EMP 的数据分别存放在表段 EMP 和索引段 PK_EMP 中。但是,如果经常要通过主键列检索数据,那么 Oracle 建议将这种表建立为索引组织表。当建立索引组织表时,表和其主键索引的数据会存放到同一个段中,该段被称为索引组织表段。在按索引组织的表内,数据基于主键键值存储在索引内。按索引组织的表无需在表中进行查找,因为所有数据都可以直接从索引树中检索到。

6)索引分区段(Index Partition):

索引分区类似于表分区,而且只能在分区表上建立索引分区。通过对索引进行分区,可以将一个大的索引划分成几个小的分区,并且每个分区对应一个段,这种段被称为索引分区段。分区索引的主要用途在于,通过分散索引输入/输出(I/O) 来最大限度地降低对系统资源的争用。使用这种类型的段需要在 Oracle9i 企业版内选择分区(Partitioning) 组件。

7)还原段(Undo):

还原段由正在对数据库进行更改的事务处理使用,还原段用于存放事务所修改数据的旧值。在修改表或索引数据时,Oracle 会将修改前的数据存放到还原段中,以使得用户可以取消错误操作。例如,当执行"UPDATE emp SET sal=1000 WHERE empno=7788"语句时,假定雇员 7788 原有工资为 800,那么 800 将会存放到还原段中,而新数据 1000 将会存放到EMP 段中。

8)临时段(Temporary Segment):

当用户执行 CREATE INDEX、SELECT DISTINCT 和 SELECT GROUP BY 等命令时,Oracle 服务器就会在内存中(排序区中,大小由初始化参数 SORT_AREA_SIZE 确定)执行排序。如果排序所需空间大于内存中的可用空间,则将中间结果写入到磁盘上。临时段用来存储这些中间结果。假定某表的数据为 7788,7235,8769,2020,8986,那当使用 ORDER BY 子句进行排序时,会返回数据 2020,7235,7788,8769,8986。这些返回的数据被称为临时数据,这些数据存放到临时段中。

当执行以下操作时会产生临时数据:

  • ? CREATE INDEX
  • ? SELECT...ORDERBY
  • ? SELECT DISTINCT...
  • ? SELECT...GROUPBY
  • ? SELECT...UNION
  • ? SELECT...INTERSECT
  • ? SELECT...MINUS
  • ? ANALYZE 命令

9)LOB 段:

当表中的数据包含文本文档、图像或者视频时,使用普通数据类型如 VARCHAR 等可能无法存储,必须使用 CLOB 或 BLOB 数据类型存储大型对象(LOB)。如果 LOB 列数据长度大于 4000B,Oracle 服务器将把这些值存储在独立的段(称为“LOB 段”)中。而在基表(Base Table)中只包含一个定位器或者指针,指向对应的 LOB 数据所在的位置除了上述 9 种段类型外,还有 LOB 索引段,嵌套表段,引导程序段(也称为高速缓存段)等多种段类型,在此不做介绍。

【实例3-1】查询 scott 用户拥有的段类型和个数。

1)以 sys 用户登录
CONN / AS SYSDBA已连接
2) 查询
SQL> SELECT SEGMENT_TYPE,COUNT(*) SEG_COUNTFROM dba_segmentsWHERE owner='SCOTT'GROUP BY SEGMENT_TYPE;
SEGMENT_TYPE SEG_COUNT
------------------ ----------
INDEX 3TABLE 9;

SCOTT 模式有 3 个索引段和 9 个数据段。

(二)、存储从句的优先关系

在创建段时,可以为它指定 pctfree、pctused 等参数,来控制其中块存储空间管理方式,也可以为它指定 initial、next、pctincrease 等存储参数,以指定其中区的分配方式。这些参数设置可以是数据库级别的,即使用数据库默认的区分配和管理方式,也可以在表空间级别的,即通过 EXTENT MANAGEMENT 子句及 DEFAULT STORAGE 子句指定区的分配和管理方式,也可以在段级别,即指定存储子句(DEFAULT STORAGE 子句),以控制如何向段分配区。那么存储子句的优先关系如何呢,Oracle 服务器按以下的方式进行区的管理(如图 P1-1所示):

  • ? 除了 MINIMUM EXTENT 和 UNIFORM SIZE 表空间参数外,在段级别指定的任何存储参数优先级最高,覆盖在表空间级别设置的相应选项。
  • ? 如果没有在段级别明确设置存储参数,那么存储参数缺省值为在表空间级别所设置的值。
  • ? 如果没有在表空间级别明确设置存储参数,那么将使用 Oracle 服务器系统的缺省设置。

还要注意,某些参数无法在表空间级别指定,而只能在段级别指定。如果存储参数改变,参数的改变只影响新分配区,而对已分配的区不产生影响。如果指定了表空间的最小区大小,分配给该表空间内的段的最小区个数是固定的。

四、区的分配和撤销

数据扩展(extent)是由一组连续的数据块(data block)构成的数据库逻辑存储分配单位。而段(segment)则是由一个或多个数据扩展构成。当一个段中已有空间已经用完,Oracle为这个段分配新的数据扩展。

(一)、数据扩展何时被分配

当用户创建数据表时,Oracle 为此表的数据段(data segment)分配一个包含若干数据块(data block)的初始数据扩展(initial extent)。虽然此时数据表中还没有数据,但是此初始数据扩展中的数据块已经为插入新数据做好了准备。

如果一个段(segment)的初始数据扩展(initial extent)中的数据块(data block)都已装满,且有新数据插入需要空间时,Oracle 自动为这个段分配一个增量数据扩展(incrementalextent)。增量数据扩展是一个段中继已有数据扩展之后分配的后续数据扩展,她的容量大于或等于之前的数据扩展。

为了管理的需要,每个段(segment)的段头(header block)中包含一个记录此段所有数据扩展(extent)的目录。

(二)、如何决定数据扩展分配时的数量与容量

每个段(segment)的定义中都包含了数据扩展(extent)的存储参数(storage parameter)存储参数适用于各种类型的段。这个参数控制着 Oracle 如何为段分配可用空间。例如,用户可以在 CREATE TABLE 语句中使用 STORAGE 子句设定存储参数,决定创建表时为其数据段(data segment)分配多少初始空间,或限定一个表最多可以包含多少数据扩展。如果用户没有为表设定存储参数,那么表在创建时使用所在表空间(tablespace)的默认存储参数。

用户既可以使用数据字典管理的表空间(dictionary managed tablespace)(依赖数据字典表监控空间的利用情况),也可以使用本地管理的表空间(locally managed tablespace)(使用位图(bitmap)来标记可用与已用空间)。由于本地管理的表空间性能较好且易于管理,当用户没有显式地设定数据扩展(extent)管理参数时,除了 SYSTEM 之外的所有永久表空间(permanent tablespace)默认使用本地管理方式。

在一个本地管理的表空间中,其中所分配的数据扩展(extent)的容量既可以是用户设定的固定值,也可以是由系统自动决定的可变值。当用户创建表空间(tablespace)时可以使用 UNIFORM (用户指定)或 AUTOALLOCATE (由系统管理)子句设定数据扩展的分配方式。对于固定容量(UNIFORM)的数据扩展,用户可以为数据扩展设定容量或使用默认大小(1 MB)。用户须确保每个数据扩展的容量至少能包含 5 个数据块(database block)。本地管理(locally managed)的临时表空间(temporary tablespace)在分配数据扩展时只能使用此种方式。

对于由系统管理(AUTOALLOCATE)的数据扩展,由 Oracle 决定新增数据扩展的最佳容量,其最小容量为 64 KB。如果创建表空间时使用了“segment space management auto”子句,且数据块容量大于等于 16 KB,Oracle 扩展一个段时(segment)所创建的数据扩展的最小容量为 1 MB。对于永久表空间(permanent tablespace)上述参数均为默认值。

在本地管理的表空间(locally managed tablespace)中,INITIAL,NEXT,PCTINCREASE, 和 MINEXTENTS 这四个存储参数可以作用于段(segment),但不能作用于表空间。INITIAL,NEXT,PCTINCREASE,和 MINEXTENTS 相结合可以用于计算段的初始容量。当段容量确定后,Oracle 使用内部算法确定其中每个初始数据扩展(extent)的容量。

(三)、数据扩展如何被分配

依据表空间管理方式的不同(本地管理(locally managed)或数据字典管理(dictionarymanaged)),选择不同的算法分配数据扩展(extent)。

对于本地管理的表空间(locally managed tablespace),Oracle 在为新的数据扩展(extent)寻找可用空间时,首先选择一个属于此表空间的数据文件(datafile),再搜索此数据文件的位图(bitmap)查找连续的数据块(free block)。如果此数据块中没有足够的连续可用空间Oracle 将查询其他数据文件。

举例说明,当创建表段时,Oracle 将为段分配一个“初始区”(Initial Extent),时,由于表不存在任何数据,初始区中的每个块每是未使用的。随着不断向表插入数据,始区的块不断写满,当初始区中的块都被写满后,数据段会向 Oracle 申请新的存储空间,这时 Oracle 为表段再分配一个“后继区”,后继区写满后再分配新区。这些区被标记为“已用区”通常分配给段的区将一直保留在段中,不论区中是否存有数据.当删除数据库对象时,组成对象段的所有区全部回收,即变为“空闲区”。


写在最后的话

感谢各位的支持与阅读,后续会继续推送相关知识和交流,欢迎交流、转发和关注,感谢!

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言