快速深入地掌握和管理数据库系统-第四章
 
2009-01-13 来源:chinaunix.net
 

第四章 存储管理

数据库是数据的集合,这些数据按照一定的格式存放在磁盘中,在处理时被读入内存。由于I/O操作一般是系统的运行瓶颈,为提高系统地I/O处理速度,数据库管理员在创建数据库时,应当仔细地规划磁盘空间的使用;在系统运行过程中,应当根据需要进行数据磁盘空间的整理。

了解数据如何在数据库中存放以及系统如何访问和管理这些数据,将有助于用户更好地管理和控制数据库系统。本章首先从物理和逻辑两个层面上介绍数据库的存储结构,然后就常用数据库系统的存储结构进行了讲解。由于表、索引是数据库中存放数据的主要对象,系统对数据的访问和管理也是基于表、索引来完成的。因此,关于表、索引的使用、管理和维护也是本章讲解的重点。

4.1 数据库存储结构

在应用系统发展的早期,应用程序和数据紧密结合在一起。一个应用程序只用来处理特定的一批数据,而特定的数据也只为一个程序所使用。随着数据库系统的出现,应用程序和数据做到了物理和逻辑上的独立。多个应用程序可以共享数据库中的数据,而数据库中数据结构的改变,不需要改动应用程序。

一般用户不需要知道数据在数据库中如何存放。然而对数据库管理员来说,需要在安装、配置数据库时,决定数据的存放方式和位置;需要在系统运行过程中,调整数据存放以提高系统性能。如果数据库管理员能够在最初安装、配置数据库时,根据应用程序的特性,仔细地规划、合理地安排数据的存放,就能够极大地减少系统运行过程中对磁盘的I/O操作,这必然会带来系统性能的提高。

在规划数据的存放之前,我们首先要对数据库的存储结构有所了解。数据库的存储结构可分为物理结构和逻辑结构(如图4-1)。

4.1.1 数据库的物理结构

数据库的物理结构比较明确、简单,就是由许多个物理上互相独立的数据文件组成。这里的数据文件,可以是操作系统文件,也可以是裸设备,在数据库创建时被建立。

数据库中的所有数据、控制信息,按照一定的格式保存在这些数据文件中。数据库管理系统就是作为一个接口,方便用户管理和维护这些数据。

使用裸设备作为数据文件,数据库系统通过操作系统的低层调用,直接操作磁盘空间。而使用操作系统文件作为数据文件,数据库系统对数据的读写、访问要经过操作系统。因此,在对系统性能要求较高的应用环境中,最好能够使用裸设备创建数据库。

由于操作系统采用分页存储管理,内存和外部存储空间按照相同的尺寸分页,这个页就是操作系统页,也称为操作系统块、物理页、物理块。这样,数据文件就由操作系统数据页组成。

操作系统页是操作系统读写磁盘的基本单位。操作系统按照这个尺寸从磁盘读数据到内存,同样按照这个尺寸将数据从内存写入磁盘。对特定的操作系统平台,这个页尺寸是固定的,无法更改(对UNIX平台,页尺寸为4K;对WINDOWS平台,页尺寸为2K)。

4.1.2 数据库的逻辑结构

相对于物理结构,数据库的逻辑结构有些复杂,从上到下可依次划分为:表空间(table space)、段(segment)、扩充(extent)、数据库块。

1. 表空间

表空间是一个逻辑单元,是数据库中存放表和索引数据的磁盘空间,包含多个物理上的数据文件,这些数据文件可以存放在不同的磁盘上。通过表空间,将系统对数据的存取、访问和物理上的数据文件割裂开来。

表空间对于数据库,就好似操作系统中的文件系统一样。在系统管理员创建好文件系统之后,用户可以方便地存放数据文件,随意地读写,不用关心文件在物理上如何存放。同样,使用表空间,用户操作数据库中的数据,就不必关心数据的实际存储方式了。

在一个数据库系统中,根据表空间的使用方式,一般会建立以下的表空间:

(1)系统表空间。存放数据字典等系统相关信息。

(2)用户表空间。存放用户表和索引的数据。

(3)临时表空间。存放临时表、排序及连接过程中的中间结果。

(4)日志表空间。存放系统产生的事务日志信息。

2. 段

段是表空间中磁盘空间的集合,和数据库中的表、索引密切相关。在一个表空间中,为一个表、索引分配的所有磁盘空间就组成一个段。每一个段都有一个特定的数据结构,存放在表空间中的所有表、索引都有一个对应的段存在。

向表中插入数据时(也同时引起索引中数据的插入),系统首先要检查该表中是否有可用空间。如果没有可用空间,系统就为该表分配新的磁盘空间,这些磁盘空间可以来自表空间所属的任何数据文件。因此,一个段所包含的磁盘空间可以在物理上不连续。

在正常情况下,一个表、索引就对应一个段。如果表、索引被分区,数据被分成几部分存放在几个表空间中,那么每一个表空间中的磁盘空间就组成表、索引的一个段。在这种情况下,一个表、索引就由多个段组成。

3. 扩充

扩充是一块连续的磁盘空间,是数据库中存储空间的分配单元,数据库系统按照此单位为需要磁盘空间的表、索引分配空间。

如果系统发现表、索引没有可用空间,就按照扩充的大小,为它分配新的磁盘空间。在进行空间分配时,系统从表、索引所在表空间中选择一个数据文件,检查该数据文件中是否有连续的空闲空间,可以满足扩充的空间要求。如果找到,就从该数据文件中分配扩充,否则就继续检查其它的数据文件。如果表空间的所有数据文件中,都不存在一块连续的磁盘空间,可以满足一个扩充的空间要求,那么空间分配失败,系统报错。

数据库系统以扩充为单位,对表、索引进行空间分配,主要是对以下几个方面进行考虑、平衡的结果:

(1)表、索引中的所有页应当相邻,以获取最好的系统性能。

(2)大多数表空间为多个表、索引所共享。

(3)一些表、索引的尺寸事先不能确定。

(4)表、索引中的数据在不同的时间、以不同的速度增长。

因为表、索引的尺寸无法确定,系统无法事先分配磁盘空间,只能在它们需要时进行分配。而使用数据库页进行空间分配,必然使多个表、索引的数据页大量交叉,数据的连续性将遭到破坏,进而极大地影响到系统的性能。基于这两个方面的考虑,数据库系统就以扩充作为磁盘分配的单元,一个扩充至少要包含8个数据页。

在表、索引中的数据被删除而释放了空间后,系统将检查释放的空间。如果连续的磁盘空间达到一个扩充的尺寸,系统就进行回收,从而该磁盘空间可以分配给其它的表、索引。

4. 数据库页

数据库页又称为数据库块、逻辑页、逻辑块,是数据库读写磁盘的单位,其页尺寸(也称为块尺寸)为操作系统页尺寸的倍数。

每一个操作系统平台,都有一个读写磁盘的页尺寸。操作系统使用这个尺寸,对磁盘进行数据的读、写操作。对特定的操作系统平台,这个页尺寸是固定的,用户无法修改。

数据库的页尺寸,是基于、但又不同于操作系统的页尺寸,它是数据库系统对磁盘读写的最小单位,是操作系统页尺寸的倍数。数据库以此为单位,请求磁盘中的数据。如果页尺寸为2K,则数据库系统可以一次从磁盘读取2K数据;如果页尺寸为4K,则可以一次读取4K数据。在创建数据库时,如果没有明确指定,数据库缺省就使用操作系统的页尺寸。

在一些数据库系统中,只允许使用一个页尺寸,在创建数据库时设定,然后就不能修改。而在另一些数据库系统中,可以设定单个表空间的页尺寸,不同表空间可以使用不同的页尺寸,从而系统对不同的数据文件、表空间进行操作时,可能需要使用不同的页尺寸读写磁盘上的数据。

如果数据库系统使用了多个页尺寸,就需要在内存中建立多个具有不同页尺寸的数据缓冲区。一个数据缓冲区,只能存放具有相同页尺寸表空间中的数据。如果没有对应页尺寸的数据缓冲区,表空间中的数据就无法被读取。

由于数据库系统是对用户数据的管理和维护,因此使用大的页尺寸可以提高数据的磁盘读些速度。

4.1.3 数据库结构部件之间的相互关系

对于数据库的物理和逻辑存储结构,其组成的各个部件之间关系紧密,他们之间的相互关系可以见图4-2。其中:

(1)一个表空间可以包含一个或者多个数据文件,一个数据文件只能属于一个表空间,它们之间是一对多的关系。

(2)一个表空间可以包含多个段,一个段只能属于一个表空间,它们之间是一对多的关系。

(3)一个段可以包含多个扩充,一个扩充只能分配给一个段,它们之间是一对多的关系。

(4)一个段中的扩充可以来自多个数据文件,一个数据文件可以包含多个段中的扩充,它们之间是多对多的关系。

(5)一个扩充是一块连续的磁盘空间,只能属于一个数据文件;一个数据文件,根据其空间大小,可以划分为多个扩充,它们之间是一对多的关系。

(6)一个扩充包含多个逻辑页,一个逻辑页只能分配给一个扩充,它们之间是一对多的关系。

(7)如果一个逻辑页由多个物理页组成,由于一个物理页只能属于一个逻辑页,因此它们之间是一对多的关系。如果逻辑页的页尺寸等于物理页的页尺寸,那么它们之间是一对一的关系。

此外,从图4-2中我们也可以看出:如果表或者索引被分区存放在多个表空间中,那么该表或者索引就由多个段组成。

4.2 控制数据的存放和读取

在数据库的所有对象中,只有表、索引被用来存放数据,需要磁盘空间。因此对数据存放和读取的控制,就是对表和索引中数据的控制,这就涉及到表空间、扩充、页尺寸、填充因子等的使用和选择。

4.2.1 表空间的使用原则

一个数据库要包含多个表空间,根据需要存放不同的数据。数据库管理员在创建表空间时,应当仔细地考虑和规划,合理的数据存放会极大地提高数据库系统的性能。一般来说,对表空间的使用可以遵循以下的原则:

(1)在系统性能要求较高的应用环境中,创建表空间时使用裸设备作为数据文件。

(2)将表、索引分开存放在不同的表空间中。事务对数据的处理,一般需要同时访问表及其表上的索引。分开存放表和索引,将避免磁盘的读写竞争,提高系统对事务的并行处理能力。

(3)将访问频度高的表、索引分开存放在不同的表空间中,这些表空间所使用的数据文件需要位于不同的磁盘上。这样,可以有效地避免多个访问频度高的表、索引对磁盘的读写竞争。

(4)将数据量大、访问频繁的表、索引单独存放在一个表空间中,避免该表、索引和其它表、索引的磁盘竞争。为了进一步提高这些表、索引的读写速度,可以考虑将表、索引进行分区。

(5)将日志和数据放置在不同的磁盘上。由于日志信息被连续、顺序地写入磁盘,和数据的随机读取、更新方式相冲突。分开日志和数据的存放,将避免磁头的来回移动,提高I/O处理速度。

4.2.2 扩充尺寸的选择

在创建表空间时,需要指定扩充的大小,该尺寸就成为表空间的磁盘空间分配单位。如果没有明确指定,就使用系统的缺省设置。缺省情况下,一个扩充等于8个逻辑页。

使用大的扩充尺寸,可以保证表、索引有更多的连续磁盘空间,有利于提高数据的读写速度。然而大的扩充尺寸,可能会造成磁盘空间的浪费,已分配给表、索引的扩充,即使没有被使用,也不能被其他的表、索引使用。

在有足够磁盘空间的系统环境下,可以考虑大的扩充尺寸。

4.2.3 合理设置页尺寸

数据库管理员在创建数据库、表空间时,应当考虑页尺寸的选择。在以下情况下,可以考虑使用大的页尺寸:

(1)表中有很多字段,或者一条记录需要大量的存储空间。对数据库的一个表来说,一条记录只能存放在一个逻辑页中。

(2)数据库用做查询处理。使用大的I/O尺寸,可以减少I/O次数,提高处理速度。

然而使用大的页尺寸,也会带来以下的问题:

(1)需要消耗更多的内存资源。例如要查询一条记录,则包含该记录的整个数据页需要被读入内存,从而占用更多的内存空间。只有在系统有足够内存资源的情况下,才可以考虑使用大的页尺寸。

(2)造成磁盘空间的浪费。对磁盘的数据写操作,以页尺寸为单位,小于页尺寸的数据也需要一个数据页。对较小事务处理的应用系统,大的页尺寸会造成磁盘空间的极大浪费。

一般来说,对交互式应用系统,由于事务处理较小,可以考虑较小的页尺寸;对决策支持系统,大多数处理是对数据的查询和汇总,可以考虑较大的页尺寸。

4.2.4 填充因子

填充因子(fill factor),也称为分配因子,是表和索引的一个常用数据页使用特性。它是一个百分比值,数据库系统使用此百分比,决定一个数据页中有多少空间可以用来存放数据。

在创建表、索引时,可以指定填充因子。如果填充因子等于100,则数据页中的所有空间都用来存放表、索引中的记录,在一个数据页被写满之后,才开始写下一个数据页。如果填充因子小于100,则数据页中会预留部分空间,不存放表、索引的记录。例如:填充因子等于80,则页空间的80%用于存放数据。一旦数据占用的空间达到这个限制,系统就开始操作下一个数据页。

这里需要说明的是,数据库系统只是最初向数据页中写入数据时,才会根据填充因子,决定数据页中可以存放的数据量。数据页中的剩余空间,随后还可以存放数据。

除了填充因子之外,特定数据库系统还会使用其他一些参数,来控制数据页中数据的存放。

4.2.5 指定空间使用特性

基于对数据库存储结构的了解,数据库管理员在创建表、索引时,可以根据应用系统的特性,设定表、索引使用的磁盘空间特性。有关表、索引对这些空间特性的使用原则,可见第4.3.2、4.4.4两节。

4.2.6 数据的整理

数据库系统经过一段时间的运行处理,表、索引使用的磁盘空间会出现空间不连续、存在空间碎片等问题。为了提高数据的I/O读写速度,管理员需要定期维护表、索引中的数据。有关表、索引的数据维护,可见第4.3.3、4.4.5两节。

4.3 表的管理和维护

数据库中的表用来存放数据,每一个表都有自己的结构。用户在定义好一个表之后,就可以使用SQL语句,向表中插入数据,也可以对表中已有的数据进行修改、删除以及查询操作。

4.3.1 系统对表的处理

用户创建表时可以指定表的空间尺寸,系统根据此设置为表分配磁盘空间。然而一般来说,由于无法预知有多少数据要存入表中,也就不能预测一个表需要多大的磁盘空间,从而无法在创建表时进行磁盘空间的分配。大多数情况下,表的空间分配在需要时进行。当向表中插入数据时,如果没有可用空间,系统就根据扩充的大小,为表分配新的磁盘空间。

用户使用SQL语句操作表,在长时间地对表进行增加、修改、删除操作之后,表的记录以及磁盘空间使用会出现以下的情况:

(1)表中存在记录的转移

表中的一条记录被更改之后,记录的长度可能会增加,以至于无法在当前页存放该记录。在这种情况下,系统将会寻找一个新的页,将整个记录存放在这一新页上,而在该记录的原有页上存放记录的指针,指向新页。

系统在访问被转移的记录时,需要两次的页读取。从原有页中获得新页的指针,再找到需要的记录。如果表中存在大量的记录转移,则会由于额外的I/O操作而影响系统的性能。

(2)表的数据页中存在未回收空间

表中的记录被删除或者记录被更改而长度缩短时,数据页中就会出现空闲空间。如果对表频繁进行删除或者导致记录缩短的更改,则未回收空间可能积累到一定的程度而削弱系统性能。

(3)表中的扩充不连续

一个表空间可以为多个表所使用,系统在表需要时才为它分配磁盘空间。在运行一段时间之后,一个表可能包含很多个扩充,这些扩充在空间上并不连续。表的这种不连续磁盘空间使用,会严重影响表扫描等大数据量的处理。

4.3.2 表的创建

我们在创建表时可以选择特定参数,控制表的磁盘空间使用,进而影响数据在表中的存放,提高表的访问性能。一般来说,有以下的原则需要考虑:

(1)创建表时,指定表空间。

为表设定表空间,表的磁盘空间使用就局限于该表空间,在该表空间拥有的磁盘空间中分配。只要表空间中存在空闲空间,表就可以在需要时进行空间的扩充。

可以将应用系统中具有高访问频率的表分开放置在不同的表空间中,避免它们对磁盘的I/O竞争。如果可能的话,还可以将它们放置在单独的表空间中。

(2)创建表时,指定扩充。

尽管要精确计算表的空间使用是不可能的,但大体上的估计还是可以做到的。通过估计表的空间使用,选定表的扩充尺寸,尽可能使表中数据存放在连续的磁盘空间上。

(3)创建表时,指定填充因子及其它数据存放特性。

不同的表在数据库中有不同的使用特性。一些表可能一般只用于查询,表中数据很少被改动;而另一些表可能正好相反,表中数据不断被更新。还有一些表,其数据处理特性处于以上两种表之间。表的这种不同使用特性,决定创建表时,如何选定填充因子及数据页使用特性。

对大多数情况下只用于查询的表,设置填充因子为100,数据页中的全部空间都用于存放数据。这样在相同的数据量下,一方面表所需要的数据页较少,节省了磁盘空间;另一方面系统在处理数据时,需要较少的内存空间,需要较少的磁盘I/O操作。而对不断被更新的表,设置填充因子小于100,在数据页中预留部分空间,可以有效地避免记录转移。

4.3.3 表的维护

对数据库中不断被更新的表,在经过一段时间的处理之后,表中数据及磁盘空间使用就出现以下问题:表中存在记录的转移、表的数据页中存在未回收的空间、表中的扩充不连续等;同时,数据字典中有关表的统计信息已不能准确反映表中数据的真实情况,优化器使用这些不准确的统计信息,就不能为相关SQL语句,生成合理的执行计划。

对不断被更新的表,数据库管理员应当定期地或者在大批量的数据处理之后进行以下维护:

(1)重新收集表的统计信息。

(2)重新构建表。使用相关工具,检查表中数据及磁盘空间使用。如果发现大量记录的转移、未回收的空间,就需要重新构建表。在重构表时,首先需要导出表中数据,在删除并重建表后再装入数据。

4.4 索引的管理和维护

数据库中的数据被存放在表中。为了提高访问速度,可以为表建立索引。对用户来说,索引并不是必须的。索引的存在,不但要占用磁盘空间,而且会降低数据更新的效率。但正像一个大型图书馆要为所有的图书建立图书索引一样,表上的索引将极大地方便用户对数据的访问。

4.4.1 为什么要使用索引

索引方便用户对数据的访问。在应用系统中,为数据库中的表建立正确、合理的索引,可以极大地提高应用系统的性能:

(1)在存取数据时,避免进行表扫描。没有索引,对表中数据的任何访问都要进行表扫描。在表上建立索引,虽然不会完全避免表扫描的执行,但会大大降低它的执行次数。

(2)在点查询中,定位到包含特定值的特定数据项。使用索引,可以快速地定位单条记录在表中的位置,通过两次磁盘读,就可以获得该记录的数据。相对于表扫描来说,其处理速度的提高是不言而喻的。

(3)在域查询中,建立读取数据的上限和下限。对某一范围的记录查询,通过索引可以获取记录在表中的存储范围,从而减少查询的I/O操作。

(4)在索引覆盖一个查询时,完全避免对表的存取。如果一个查询涉及的字段都包含在索引中,数据库系统就使用索引访问,代替对表的访问。由于索引中字段少、每个数据页包含更多的记录,将减少查询的I/O操作。

(5)使用有序数据,避免排序操作。对一个查询,如果要求对处理结果进行排序,那么在查询时使用索引,将会避免排序操作的执行。

(6)在表连接时,选择更合理的连接顺序和连接方式。对于需要进行连接的表,优化器会根据表上是否存在索引,选择表的连接顺序和连接方式。

此外,在表上建立索引,还可强制实现数据的唯一性。合理地创建表的聚集索引,会使插入表中的记录随机地存放。

4.4.2 索引的结构

用户不能使用SQL语句直接访问索引,直接增加、修改、删除索引中的记录。对索引的访问和维护,由数据库系统自动完成,系统根据用户对表的更新操作更新索引中记录。

用户访问带索引的表时,将由系统决定是使用索引访问,还是使用表扫描。索引中记录存贮在索引页上,索引页使用的磁盘空间在需要时分配。索引记录中包含键值和指针。键值就是创建索引所使用取值字段的,整个索引中的记录就按照键值被排序存放;指针指向下一级的索引页或者表的数据页,索引中的所有索引页就通过指针连接起来。

B树索引是数据库中应用最广泛的索引方式,它采用平衡树结构,每个叶结点到根的路径长度相同。下面我们就以B树为例,说明索引的结构(如图4-3)。

一个索引中的数据页可以分为:根页(root page)、叶页(leaf page)、分支页(branch page)。

根页是整个索引中的最高一级,一个索引只能有一个根页。如果索引很小,所有的记录可以存放在一个索引页中,那么该索引没有叶页和分支页,根页中就存储着指向数据页的记录号。

叶页是索引的最低一级,包含表中每一记录的键值及记录号,记录以键值的排列顺序存储。系统通过索引访问表中记录,就是根据键值找到键值所在的叶页以及对应的索引记录,然后使用索引记录中的记录号,找到表中记录的位置。

根页和叶页之间的所有索引页称为分支页。分支页中的每一条记录都指向下一级的分支页或者叶页,一个大型表上的索引可能需要许多分支页。

4.4.3 系统对索引的处理

根据用户对表中记录的处理,数据库系统相应地维护索引中的记录,从而使表和索引在数据上保持一致。

1. 查询记录

用户要查询表中记录,系统首先判断是否可以使用索引。在使用索引访问的情况下,首先从索引的根页开始,找到小于或者等于搜索码值的最大键值,根据键值对应的指针,走到下一级的索引页。在下一级索引页,仍旧沿用以上方法,从而一直到达索引的叶页。到达叶页之后,系统就可以确定能否找到该搜索码值。如果找到,就使用记录号定位到表中的记录。

例如:在图4-3中,要查找搜索码值Dull,系统按照以下的路径查找:页1001→页1007→页1132→页1296。

2. 插入记录

用户向表中插入记录,将引起数据库系统对索引中记录的插入。往索引中插入记录时,系统首先使用和查询记录相同的方法,找到要插入键值应当放置的叶页。在找到要插入的叶页之后,根据叶页当前的空间使用情况,系统会采取不同的处理方法:

(1)叶页有可以使用的空闲空间。系统保证叶页中键值的顺序,在适当位置插入该键值。

(2)叶页没有可以使用的空闲空间。这种情况下,需要对叶页进行拆分。首先,系统为索引分配一个新的叶页(如果索引没有可用空间,就首先进行磁盘空间的分配),在索引的页链中加入这个新的叶页。然后,原有叶页中大约半数的记录被移动到新的叶页,新的键值也按照顺序被插入。

由于在索引中增加了一个新的叶页,因此需要在上一级的分支页中插入记录,以指向这个新的叶页。如果上一级分支页同样没有可用空间,就按照相同的方式进行页的拆分。在最坏的情况下,从叶页、分支页,一直到根页,都没有可用空间,需要在索引页的各个级别上进行页的拆分。

对根页的拆分,系统需要生成新的根页,在根页中使用两个指针指向原有根页被拆分后的两个索引页,这两个索引页就变成分支页。

例如:在图4-3中,要插入码值Flood,需要进行叶页的拆分,拆分后见图4-4。

3. 删除记录

用户删除表中记录,将引起数据库系统对索引中记录的删除。删除索引中记录时,系统首先使用和查询记录相同的方法,找到要删除键值所在的叶页,然后从该叶页中进行键值的删除。在删除操作完成之后,根据叶页的空间使用情况,系统会采取不同的处理方法:

(1)叶页中仍包含键值。这种情况下,系统不做任何处理。

(2)叶页中没有包含任何键值。就是说,叶页没有包含任何记录。这种情况下,需要对叶页进行归并,将不再需要的叶页从索引的页链中删除,同时从上一级的分支页中删除指向该叶页的指针。如果上一级分支页同样没有包含任何记录,就按照相同的方式进行页的归并。

例如:在图4-3中,删除码值Karsen,需要进行叶页的归并,归并后见图4-5。

4. 更改记录

用户更改表中记录,如果索引所使用的字段被更改,将引起数据库系统对索引中记录的更改。系统对索引中记录的更改,是首先将原有键值从索引中删除,然后再将新的键值插入索引,其处理过程可见以上索引中记录的删除和插入。

4.4.4 索引的创建

一般情况下,索引的空间分配在需要时进行。当向索引中插入数据时,如果没有可用空间,系统就根据扩充的大小,为索引分配新的磁盘空间。创建索引时,我们可以使用参数,控制索引的磁盘空间使用,进而影响数据在索引中的存放,提高系统性能。一般来说,创建索引时遵循以下规则:

(1)创建索引时,指定表空间。设定索引使用的表空间,就使索引的空间分配局限于该表空间,从而控制索引的数据存放。

(2)应当将索引和它所从属的表分开放置在不同的表空间中。由于系统对数据的处理,要同时访问表及其表上的索引,将它们分开存放,将避免对磁盘的互相竞争。

(3)创建索引时,指定扩充。通过估计索引的空间使用,选定索引的扩充尺寸,尽可能使索引中数据存放在连续的磁盘空间上。

(4)创建索引时,指定填充因子及其它数据存放特性。索引和所从属的表有相同的使用特性。对大多数情况下只用于查询的表,其索引也很少被改动,可以设置填充因子为100;对不断被更新的表,其索引也处于变动之用,可以设置填充因子小于100,避免索引页的拆分和合并。

有关索引创建的更多原则性要求,可以进一步参看第5.6.1一节。

4.4.5 索引的维护

在数据库中,不断被更新的表需要定期维护,表上的索引也同样需要定期维护。经常被更新的索引,经过一段时间的使用后会存在以下的问题:索引页在空间上不连续、出现索引页拆分和归并的几率增大。另外,数据字典中有关索引的统计信息也不能正确反映索引中数据的真实情况。

对不断被更新的表,数据库管理员应当定期地维护表上的索引:

(1)重新收集索引的统计信息。

(2)重新构建索引。删除表上的现有索引,重新创建。

4.5 表和索引的分区

表和索引的分区,就是将表和索引中的记录数据分成多个部分,分开存放在多个表空间中,也就是将表、索引分成多个段,每一个段就是一个分区。

有多种实现方式,可以对表、索引进行分区。我们经常使用的方式有以下两种:

(1)按某字段的取值。在向表中插入记录时,系统根据字段的取值,决定将记录存入表、索引的那一个分区。每一个分区对应字段的不同取值区间。对现有记录的更改,也将引起记录在不同分区之间的移动。

(2)随机存放。在向表中插入记录时,系统随机地将记录存入到不同的分区中,使各个分区有大体上相同的记录数量。

表和索引是否分区、使用什么样的分区方式,在创建表、索引时指定。如果要将现有的表、索引分区,可以首先导出表中的数据,重新创建表、索引后再导入数据。一般来说,要分区的表、索引应具备以下的条件:

(1)包含大量的记录。没有必要对数据量小的表、索引进行分区。

(2)经常被访问,要求比较高的访问速度。

分区对用户是透明的,用户不用关心表、索引是否被分区。用户向表中插入记录时,由系统根据表、索引的定义,存放记录到对应的分区中;在查询表中记录时,由系统根据查询条件,决定要访问那一个分区,抑或是所有分区。

对大数据量的表和索引分区,所带来的好处是显而易见的,这主要体现在数据处理性能的提高上:

(1)实现并行的查询处理。在查询处理时,数据库系统可以将单个查询分成多个子查询,每一个子查询处理一个或者几个分区。所有的子查询并行执行,最后合并各个子查询的处理结果。

(2)实现并行的数据装入。类似于并行的查询处理,在进行大批量的数据装入时,数据库系统可以并行地对每一个分区进行数据装入。

(3)分散表的I/O操作。对频繁使用的表、索引分区,使数据分布到多个磁盘上,从而将表、索引的I/O操作分散到多个磁盘上,降低了I/O操作的竞争。

(4)增加记录插入点。对存在大量记录插入操作的表、索引分区,将插入处理分散到多个分区中,这样表、索引中就存在多个插入点,可以避免由插入操作而引起的“热点”问题。

尽管表和索引的分区提高了数据处理的性能,但相应地带来了管理上的不便、维护上的困难。然而这种不便、困难不是绝对的,有时合理地使用表、索引的分区,将给数据库的管理和维护带来极大的便利。例如:定期地移走数据库中的历史数据。对管理员来说,这种数据维护工作是不可避免的。这主要是基于释放磁盘空间、提高查询处理速度的考虑,尤其是对那些包含大批量数据而数据量又随着时间快速增长的表,这种数据维护工作更是经常需要进行。这些被移走的历史数据仍旧有可能再次被使用,在需要时必须重新装入数据库。

对这种历史数据的维护,我们一般直接使用SQL语句,在进行备份后从表中删除。对包含大数据量的表,这种处理方式不但要耗费大量的时间,而且还可能造成数据库的损坏。再次需要时对这些数据的重新装入,又是费时、费力的工作。

一种更好的处理方式就是对大数据量表分区,使用分区实现历史数据的维护。在分区时,我们可以按照日期字段,将不同年份、甚至不同月份的数据存放在不同的分区中。要移走历史数据,就是移走表的分区,将分区存放到另外的表结构中。在需要访问这些数据时,将原有的分区再加入到表中就可以了。整个处理过程简单、方便、快捷,又不会对系统产生大的影响。

4.6 常用数据库系统的存储管理

常见的数据库系统:DB2、ORACLE、INFORMIX、SYBASE,在存储结构上略有不同。我们下面就针对这些具体的数据库系统,进行数据库存储结构的介绍。

尽管不同数据库系统在表、索引以及分区的实现和操作上存在很大的差异,但相关的概念大体一致。我们这里不再就这些方面进行讲解。

4.6.1 DB2数据库系统

DB2数据库的物理和逻辑结构,和我们前面讲到的数据库结构有一些区别,主要体现在:

(1)数据文件被称为容器(container)。容器可以是裸设备、操作系统文件,也可以是一个操作系统目录。

(2)系统中引入一个新的概念:分区组(partition group)。

DB2数据库的存储结构可见图4-6。

1. 分区组

分区组应用在DB2系统的并行处理环境下,它是一个或多个数据库分区(也称为节点)的集合,每一个数据库分区都属于一个分区组。

在数据库的并行处理环境中,创建表空间时需要指定分区组,这样系统就自动在分区组所包含的所有数据库分区内建立该表空间的分区。有关DB2系统的并行处理环境,本书不作详细介绍。

2. 表空间

在DB2系统中,可以创建两种类型的表空间:

(1)系统管理表空间(system managed space ,SMS)

(2)数据库管理表空间(database managed space,DMS)

系统管理表空间使用的容器都是操作系统目录,容器的空间不会预先分配,存储在表空间中的表、索引以文件的方式存放在目录中。数据库管理表空间使用的容器可以是裸设备,也可以是操作系统文件,容器的空间预先分配。

在一个数据库系统中,可以混合使用这两种表空间,用户可以根据自己的需要进行选择。一般来说,使用系统管理表空间,可以方便系统的管理和维护;而使用数据库管理表空间,将提高数据库系统的处理速度。

不论是用那种表空间,表空间中所有表、索引的数据均匀地存放在各个容器上,当其中任何一个容器没有空闲空间后,系统就认为整个表空间没有可用空间。

3. 段

DB2系统的相关资料中并没有段的概念。但由于段和表、索引密切相关,因此我们还是把它作为数据库逻辑结构的一部分。

在DB2系统中,如果在数据库管理表空间上创建表,则可以将表和表上索引分开存放在不同的数据库表空间中。如果表中包含有大对象字段(如存放图形、图象等),还可以将这些大对象字段和表中其它的字段分开,单独存放在另外的数据库表空间中。

如果使用系统管理表空间创建表,则表、索引以及表中的大对象字段只能存放在同一个表空间中,它们分别以文件的形式存放在容器的目录中。

4. 扩充

在创建表空间时,可以设定该表空间的扩充大小,存放在该表空间中的所有表、索引都使用此设置进行磁盘空间的分配。如果创建表空间时没有指定扩充大小,则该表空间使用缺省设置。DB2系统缺省的扩充大小为8个逻辑页,可以为不同的表空间设置不同的扩充大小。

表空间中的所有容器可以看作被环行排列。系统在为表、索引分配空间时,首先从环中的第一个容器开始,进行扩充的分配。在此扩充没有空闲空间后,系统从环中的下一个容器中分配扩充,以此类推,磁盘空间的分配就按照这个环循环进行。

由于这种空间分配方式,表、索引中的数据被均衡地存放在表空间中的所有容器上。如果创建表空间时,能够将每个容器都放置在不同的磁盘上,将极大地提高系统I/O的并行处理能力。也正是由于这个原因,一旦表空间的一个容器没有空间,系统就认为整个表空间不存在空间。因此应当为表空间中的容器分配相同大小的磁盘空间。

DB2系统使用位映射(bit map)方式管理扩充的分配和回收,也就是使用一个二进制位来决定一个扩充是否被使用。

5. 逻辑页

在DB2数据库中,不同的表空间可以使用不同的页尺寸。在创建表空间时,如果指定页尺寸,则存储在该表空间中的所有表、索引都使用此页尺寸进行读写。如果没有指定页尺寸,则缺省使用操作系统的页尺寸。

要在一个数据库中使用多个页尺寸,需要在数据库中创建多个缓冲池,设定不同的页尺寸。将表空间绑定到具有相同页尺寸的缓冲池上,系统对该表空间中所有表、索引的操作,都通过所绑定的缓冲池完成。

4.6.2 ORACLE数据库系统

ORACLE数据库的物理和逻辑结构,和我们前面讲到的数据库结构相同。

1. 表空间

在ORACLE系统中,根据空间的分配和回收管理方式,可以创建两种表空间:

(1)字典管理表空间(directory managed table space)

(2)本地管理表空间(locally managed table space)

字典管理表空间依赖数据字典表来跟踪空间的使用情况,扩充的分配和回收都要修改数据字典表。在Oracle8i之前,所有表空间的空间管理都采用字典管理方式。表空间的字典管理方式,增加了系统对数据字典表的访问竞争。因此在Oracle8i之后,ORACLE公司已经不建议用户使用字典管理方式。

对本地管理表空间,其每一个数据文件的头部都有一个BITMAP,BITMAP中的每一位都对应这个数据文件的一个或者一组数据块。当分配或者回收扩充时,ORACLE系统都要修改这些BITMAP,以反映这些数据块的状态。本地管理表空间具有更好的性能、更容易管理。

2. 扩充

在ORACLE系统中,扩充的大小是基于单个的表、索引来设定的。在创建表、索引时,可以设定该数据库对象的扩充大小,可以指定其起始扩充大小以及随后进行分配的扩充大小。如果不指定扩充大小,则该数据库对象使用缺省设置。系统缺省的扩充大小为8个逻辑页。

对扩充的分配、回收管理,由表空间的空间管理特性决定。

3. 逻辑页

在ORACLE系统中,不同的表空间可以使用不同的页尺寸。在创建表空间时,如果指定页尺寸,则存储在该表空间中的所有数据库对象都使用此页尺寸进行读写。如果没有指定,则使用系统缺省设置。

要使用不同的页尺寸,需要在系统中建立多个不同页尺寸的数据缓冲区,作为处理相应数据库对象中数据的内存空间。下列配置参数,用来设置不同页尺寸下的数据缓冲区:

DB_nK_CACHE_SIZE:设定具有nK页尺寸的数据缓冲区的大小。其中n可以为2、4、8、16、32。

4.6.3 INFORMIX数据库系统

INFROMIX数据库的物理和逻辑结构,和我们前面讲到的数据库结构有一些区别,主要体现在:

(1)段被称为tblspace。

(2)数据文件被称为大块(chunk)。

INFORMIX数据库的存储结构见图4-7。

1. 表空间

在INFORMIX系统中,可以创建三种类型的表空间:DBSPACE、BLOBSPACE、SBSPACE。

DBSPACE是数据库中最常用的表空间,存放我们常见的表、索引。BLOBSPACE和SBSPACE表空间用来存放大对象,比如:大数据量的图形、照片、文字等。

如果一个数据表中包含大对象字段,则在定义表时,需要为这个字段指定一个BLOBSPACE或者SBSPACE表空间,从而可以将大对象数据和表中其它字段中数据分开存放。

INFORMIX系统使用了两种类型的大对象:

(1)快捷大对象(smart large object)

(2)简单大对象(simple large object)

快捷大对象和简单大对象分别存放在BLOBSPACE和SBSPACE表空间中。一般来说,快捷大对象需要更多的磁盘空间。除此之外,对它们的处理方式也存在着差异。

快捷大对象支持数据的随机访问,可以在这个大对象数据中搜索和读写,就好象在操作一个操作系统文件。在使用SQL语句访问表中的快捷大对象字段时,系统不会返回大对象字段的真实数据。代替地系统返回一个指向大对象数据的指针,应用程序使用这个指针对大对象进行打开、读写操作。

简单大对象不支持数据的随机访问,可以使用SQL语句返回表中简单大对象字段的数据。

2. 段

在INFORMIX系统中,段被称为tblspace,和我们前面将到的段概念相同,这里不再赘述。

3. 扩充

在INFORMIX系统中,扩充的大小是基于单个的表、索引来设定的。在创建表、索引时,可以设定该数据库对象的扩充大小,可以指定其起始扩充大小以及随后要分配的扩充大小。如果不指定扩充大小,则该数据库对象使用缺省设置。系统缺省的扩充大小为8个逻辑页。

INFORMIX系统使用位映射(bit map)方式管理扩充的分配和回收,也就是使用一个二进制位来决定一个扩充是否被使用。

4. 逻辑页

在INFORMIX系统中,数据库的逻辑页大小是固定的,就是等于操作系统的页尺寸。也就是说,数据库使用了和操作系统一样的数据页,不允许用户修改。

4.6.4 SYBASE数据库系统

SYBASE数据库的物理和逻辑结构,和我们前面讲到的数据库结构有一些区别,主要体现在:

(1)表空间称为设备

(2)段的概念和我们前面讲到的段有较大的不同

SYBASE数据库的存储结构见图4-8。

1. 表空间

在SYBASE系统中,表空间被称为设备。一个设备,可以为多个数据库所使用。我们可以将一个设备的磁盘空间划分为多个部分,每一部分称为设备的一个分片(fragment),分别交给不同的数据库使用;也可以将整个设备的所有空间都交给一个数据库使用,这时整个设备被作为一个分片。

2. 段

在SYBASE系统中,段的概念和我们前面讲到的段有较大的不同,可以更确切地将SYBASE系统中的段看作是设备分片的集合。在创建一个数据库时,系统会自动为该数据库建立以下三个段:

(1)系统段(system segment)

(2)缺省段(default segment)

(3)日志段(log segment)

系统段存放和数据字典信息相关的系统表、索引等,日志段存放数据库事务日志数据,用户创建的数据库对象可以存放在缺省段中。

在数据库建成之后,系统段和缺省段包含相同的设备分片。如果没有为日志段指定单独的设备分片,则日志段也同样使用系统段、缺省段的设备分片。此后,用户可以向数据库中增加新的设备分片,在这些分片上创建自己的段;也可以对系统段、缺省段、日志段的设备分片使用进行调整,使它们使用不同的设备分片。用户在创建表、索引时可以指定段,从而将表、索引存放在特定的段中。如果不指定,则该表、索引就存放在缺省段中。

一个段中可以存放多个表和索引。如果在一个用户段中只存放一个表或者索引的数据,那么这个用户段就等同于我们前面讲的段了。

3. 扩充

在SYBASE系统中,扩充的大小固定为8个逻辑页,用户不能设置和更改。

SYBASE系统使用位映射(bit map)方式管理扩充的分配和回收,也就是使用一个二进制位来决定一个扩充是否被使用。

4. 逻辑页

我们可以在安装、配置SYBASE系统时,设定其页尺寸的大小。如果没有指定的话,则使用操作系统的页尺寸。在系统建成之后,数据库的页尺寸就不能再改变,所有的数据库对象都使用这个页尺寸进行读写。

如果为SYBASE系统的数据缓冲区设置了多个不同读写尺寸的缓冲池,系统在预读数据时,就可以根据该缓冲池的页尺寸,一次将多个逻辑页读入内存(最多为8个逻辑页,即一个扩充)。

4.7 本章小结

数据库是数据的集合,这些数据按照一定的格式被存储。整个数据库的存储结构,可以划分为物理结构和逻辑结构。

数据库的物理结构比较简单,就是由物理上互相独立的数据文件组成。这些数据文件在数据库创建时建立,可以是操作系统文件,也可以是裸设备。数据文件由操作系统页组成,操作系统页是操作系统读写磁盘的基本单位。对特定的操作系统平台,其页尺寸是固定的,无法更改。

数据库的逻辑结构相对来说有些复杂,从上到下可依次划分为:表空间、段、扩充、数据库块。表空间是一个逻辑磁盘空间,包含多个物理上的数据文件,存放表、索引中的数据。通过表空间,将系统对数据的存取、访问和物理上的数据文件割裂开来。

段是一个表或者索引在一个表空间中所使用磁盘空间的集合,其磁盘空间可能来自多个数据文件,在物理上并不连续。

扩充是数据库中存储空间的分配单元,它是一块连续的磁盘空间,数据库系统按照此单位为需要磁盘空间的表、索引分配空间。系统同样按照此单位,回收不再使用的磁盘空间。

数据库页是数据库读写磁盘的单位,其页尺寸为操作系统页尺寸的倍数。一个数据库中的数据库页可以有不同的页尺寸,为访问不同页尺寸的数据库页,要在系统中建立多个不同页尺寸的内存缓冲区。

数据库中的表用来存放数据,每一个表都有自己的结构。创建表时,可以考虑指定表空间、扩充、填充因子及其它数据存放特性。对不断被更新的表,经过一段时间的处理后会出现:表中存在记录的转移、表的数据页中存在未回收的空间、表中的扩充不连续等问题,管理员需要定期对表进行维护。

为提高访问速度,可以为表建立索引。创建索引时,可以考虑指定表空间、扩充、填充因子及其它数据存放特性。索引的数据页可以分为:根页、叶页、分支页,对不断被更新的索引,经常会出现:索引页在空间上不连续、出现索引页拆分和归并的几率增大等问题,管理员需要定期对索引进行维护。

表和索引的分区,就是将表和索引中的记录数据分成多个部分,分开存放在多个表空间中。管理员应当根据自身需要,选择合适的表、索引进行分区。

DB2系统的数据文件被称为容器,在并行处理环境下,其存储结构用到了分区组。

INFROMIX系统的数据文件被称为大块,段被称为tblspace。

SYBASE系统的表空间被称为设备,段的概念也和其它数据库系统不同,可以确切地看作是设备分片的集合。


火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织