
1.6 数据库的逻辑结构
前面已经提到,数据库服务器包括实例和数据库两部分。其中,数据库用来存储数据,而实例用来访问数据库中的数据。实例包括一组内存结构和后台进程,而数据库的结构需要从逻辑结构和物理结构两个方面来理解。数据库的逻辑结构是指数据的逻辑组织形式,是Oracle内部用来管理数据的机制。数据库的物理结构是从用户角度感觉到的结构,是在操作系统中存储和管理数据的机制。
从逻辑结构上来讲,一个数据库包含若干个表空间,不同类型的数据存储在不同的表空间中,如系统数据、用户数据、临时数据和回滚数据等分别存储在不同的表空间中。表空间中包含若干个段,同一个表空间中的数据又可进一步根据类型不同而存储在不同的段中,如数据段、索引段、临时段等。一个段中又可以包含若干个区,区是Oracle分配存储空间和回收存储空间的基本单位。区是由连续的多个数据块组成的,数据块是Oracle读/写数据库的基本单位。表空间、段、区和数据块组成了数据库的逻辑结构。
逻辑结构是指数据的组织形式,而从物理形式上讲,数据是以数据文件的形式存储在磁盘上的。在操作系统中,能使用户真正感觉到数据库存在的是数据文件。数据文件存储在磁盘上,它需要占用若干个操作系统块。
逻辑结构和物理结构并非毫无关系,而是紧密联系的。表空间中的数据存放在数据文件中,因此一个表空间对应一个或多个数据文件。数据块是Oracle中存储数据的基本单位,一个数据块对应若干个操作系统块,数据最终是存储在操作系统块中的,Oracle对数据块的访问最终转化为对操作系统块的访问。
数据库的逻辑结构与物理结构之间的关系如图1-12所示。

图1-12
1.6.1 表空间(TABLESPACE)
表空间是数据库中数据的逻辑组织形式,一个数据库在逻辑上由多个表空间组成。表空间用于将不同类型的数据组织在一起,就像一个公司里的员工是按照不同部门组织在一起一样。表空间中的数据在物理上是存储在数据文件中的,一个表空间对应一个或多个数据文件,就像一个部门对应若干个办公室一样。当表空间中的存储空间紧张时,可以向表空间中添加数据文件,一个数据文件只能属于一个表空间。
如果表空间中只包含一个数据文件,那么所有数据都将存储在这个数据文件中。如果表空间对应多个数据文件,那么数据将被分割成几部分,分别存放在这些数据文件中。表空间与数据文件的关系如图1-13所示。

图1-13
在数据库中引入表空间的好处有以下几点:
●将系统数据和用户数据分开,有利于保护重要的数据;
●可以限制用户对磁盘存储空间的使用;
●将临时数据与用户数据分开,从而减少用户数据存储区的碎片,提高数据库的性能;
●能够将不同类型的数据分别存放在不同的磁盘上,以减少磁盘的读/写冲突。可以将访问频繁的数据存储在速度相对较快的磁盘上,从而在整体上提高数据库的性能;
●各个表空间可以被单独设置为联机或脱机状态,这样可以在数据库正常运行的情况下,将单个表空间置于脱机状态,并对其进行备份或恢复。
在一个数据库中有5种类型的表空间,即SYSTEM表空间、SYSAUX表空间、UNDO表空间、临时表空间和普通表空间。其中前4种表空间必不可少,在创建数据库时就需要创建它们,普通表空间是根据需要才创建的。
(1)SYSTEM表空间
SYSTEM表空间是数据库中一个必需的表空间。在创建数据库时,SYSTEM表空间将被自动创建。在SYSTEM表空间中存储着数据库的系统信息,如数据字典、数据库对象的定义、PL/SQL存储程序的代码、SYSTEM回滚段等。
(2)SYSAUX表空间
SYSAUX表空间也是数据库中一个必需的表空间,它是在创建数据库时自动被创建的。SYSAUX表空间是对SYSTEM表空间的辅助表空间,以前存储在SYSTEM表空间中的数据现在存储在SYSAUX表空间中,从而减轻了SYSTEM表空间的负担。另外,许多以前需要单独表空间的数据现在都可以存储在SYSAUX表空间中,从而减少了需要维护的表空间的数目。
(3)UNDO表空间
UNDO表空间是用来存储回滚数据的。回滚数据是被事务修改的数据,例如,假设用户执行语句“DELETE FROM bmb WHERE ID=8902”,被DELETE命令访问的数据就是回滚数据。在事务尚未提交之时,这一行数据被存放在UNDO表空间中。此时,假设另一个用户执行语句“SELECT * FROM bmb WHERE ID=8902”,那么他将得到从UNDO表空间中返回的这一行数据。如果事务被回滚,UNDO表空间中的数据被写回原来的存储空间,就好像原来的DML操作没有被执行一样。
由此可见,UNDO表空间是为了回滚事务而设计的。在以前版本的数据库中,回滚数据只能存放在回滚段中。回滚段位于某一个表空间中,或者某些特定的表空间中。回滚段的管理比较复杂,需要数据库管理员手动执行烦琐的命令。目前版本的数据库都使用UNDO表空间来管理回滚数据。在UNDO表空间中只能存放回滚段,而不能存放其他类型的段,如数据段、索引段等。使用UNDO表空间的好处是可以对回滚数据进行自动管理,从而减轻了数据库管理员的负担。
(4)临时表空间
临时表空间用于存放用户访问数据库时所产生的临时数据。例如,当用户执行语句“SELECT * FROM bmb ORDER BY id”时,将对表中的数据进行排序并产生排序结果。
排序操作一般是在PGA的排序区中进行的。如果排序区的大小不足以容纳这些数据,将使用临时表空间。在临时表空间中只能建立临时段。临时段也不是永久存在的,当用户第一次在数据库中执行排序等操作时,临时段将自动产生,而当数据库关闭时,临时段的空间将被释放。正因如此,在临时表空间不允许创建永久性的数据库对象,如表、索引等。
在一个数据库中可以创建多个临时表空间。如果没有临时表空间,那么用户在执行排序等操作时可能需要使用SYSTEM表空间存储临时数据。如果在SYSTEM表空间中频繁地存储临时数据,将产生大量的存储碎片,从而降低数据库的性能。
在使用CREATE USER命令创建用户时,可以通过TEMPORARY TABLESPACE子句为该用户指定临时表空间。用户在创建之后,也可以通过ALTER USER命令为其指定临时表空间。这样,用户访问数据库时产生的临时数据将被存储在指定的临时表空间中。
(5)普通表空间
普通表空间是用户真正关心的表空间,在数据库中可以创建多个普通表空间。普通表空间用来存放用户的数据。
1.6.2 段(Segment)
表空间将数据按照类型从逻辑上分离开来,如将用户数据与系统数据分别组织在一个表空间中。在同一个表空间中,可能存在不同类型的数据库对象,如表、索引。Oracle将不同数据库对象中的数据以段的形式组织在一起。一个表空间包含多个段,但一个段只能属于一个表空间。
当用户在数据库中创建一个数据库对象时,在表空间中将自动创建一个段,以存储该对象的数据。例如,在默认情况下,一个表对应一个表段,一个索引对应一个索引段。段中存储空间的分配是以区为单位进行的。在一个段中包含若干个区。在分配段时需要指定初始的区个数。随着段中数据的增加,数据服务器将会扩充该段,为段分配所需的区,而当段中数据被删除时,空闲的区可以被回收。
在表空间中主要可以创建4种主要类型的段,它们是数据段、索引段、临时段和回滚段。在每个段中存储不同的数据库对象。
(1)数据段
数据段用来保存表中的数据,默认情况下一个表对应一个表段。在一个表段中只能存储一个表中的数据。当用户在表空间中创建一个表时,数据库服务器将自动在这个表空间中为该表创建一个段,段的名字与表的名字相同。
(2)索引段
索引段用来存储索引中的数据,当用户为一个表创建索引时,数据服务器将自动为该索引创建一个索引段,索引段与索引的名字相同,并且它们之间是一一对应的。当在表上创建主键约束或唯一性约束时,也将产生相应的索引段。
(3)临时段
临时段用于存放临时数据,当用户执行排序等操作时,将产生大量的临时数据,这些临时数据存储在临时段中。当然,临时数据是优先存储在PGA的排序区中的,这样可以提高排序的速度。如果排序区的大小不足以存放这些临时数据,才会用到临时段。临时段不是必需的,如果没有创建专门的临时段,用户的排序操作将使用SYSTEM表空间中的临时段。由于SYSTEM表空间存储着重要的系统数据,频繁地使用SYSTEM表空间将产生大量的碎片,从而降低数据库的性能,所以Oracle建议尽量创建专门的临时段,并将它存放在专门的临时表空间中。
(4)回滚段
回滚段用于存储回滚数据。当用户执行DML语句时,数据库服务器将修改后的数据存储在表段中,而将修改前的数据作为回滚数据存储在回滚段中。当用户回滚事务时,数据库服务器将回滚段中的数据重新写入表段,该事务所做的修改将取消。当用户提交事务时,回滚段中的数据将变为无效,这时用户将无法回滚该事务。在数据库中可以创建多个回滚段。当用户执行DML操作时,数据库服务器将自动为当前事务指定一个回滚段,用户也可以通过命令指定一个回滚段。在创建数据库时,系统在SYSTEM表空间中自动创建一个SYSTEM回滚段,SYSTEM回滚段用于维护Oracle内部的事务。数据库管理员可以通过命令创建其他的回滚段。
值得注意的是,Oracle 11g提供了两种管理回滚数据的方法,一种是手动管理方式,这种方法利用回滚段维护事务。另一种方法称为自动管理方式,这种方式利用专门的UNDO表空间管理回滚数据。由于回滚段的管理太复杂,Oracle建议大家使用自动管理方式,在以后的Oracle版本中,可能会取消手动管理方式。
注:Oracle 12c增加了Temporary UNDO(临时回滚段),可以减少存储在UNDO表空间的生成量和重做日志的生成频率,这是Oracle 12c的新特性。
1.6.3 区(Extent)
区是Oracle分配存储空间的最小单位,一个段由多个区组成,一个区由若干个连续的数据块组成,区的大小是数据块大小的整数倍。在创建一个数据库对象时,数据库服务器为该对象分配若干个区,以存储该对象的数据。数据库对象至少占用一个区,随着数据的增加,数据库服务器将不断为该对象分配所需的区,这些区的大小可能相等,也可能不相等。
1.6.4 数据块(Block)
数据块是Oracle中的最小存储单位,也是数据库服务器读/写数据的最小逻辑单位。数据库服务器在为段分配空间或回收存储空间时,是以区为单位进行的,而在读/写数据时,是以数据块为单位进行的。
数据库中的数据最终是存储在硬盘上的,所以数据块与操作系统中的块必然有着密切的联系。一个数据块由若干个操作系统块组成,它的大小是操作系统块的整数倍。数据库服务器在读/写数据时以数据块为单位进行,这种访问最终转化为对操作系统块的读/写。
在Oracle数据库中,有两种形式的数据块,一种是标准块,另一种是非标准块,自9i开始支持两种块的并存。标准块的大小由初始化参数DB_BLOCK_SIZE指定,所有标准块的大小都相同。非标准块的大小可以有多种情况,如2KB、4KB、8KB、16KB、32KB(但是不能与标准块的大小相同),等等。在数据库中可以使用一系列初始化参数DB_nK_CACHE_SIZE,其中n为2、4、8、16、32等。这些初始化参数系列用来为非标准块指定数据库高速缓存大小。如果在数据库中定义了非标准块,那么必须在SGA中为它定义相应的数据库高速缓存。无论是哪种数据块,它的大小在数据库创建之后就不能再修改。
数据库服务器在读/写数据时,数据块中的数据将首先被调入SGA的数据库高速缓存中,在缓存中必须为每一种大小的数据块定义缓冲区,缓存区的大小与数据块相同。当用户访问数据库时,数据块的内容被读/写到与之大小相同的缓冲区中。