1.3 Oracle数据库存储简介
我们已经了解到,Oracle数据库实际上是位于物理磁盘上的多个文件的逻辑集合,主要包括数据文件、联机日志文件和控制文件。用户的数据实际存放在数据文件里。
那么我们来想象一下,如果要获取某个具体数据的时候,比如要检索雇员表里雇员号为100的雇员信息,我们应该怎么做?
我们知道雇员信息是位于数据文件里的,那么最简单的方法就是从第一个数据文件的起点开始,依次读取每个文件的最小组成单位(如果位于操作系统上,则操作系统块就是它的最小组成单位,每个数据文件都由许多个操作系统块组成;如果直接放在磁盘上,比如裸设备或ASM磁盘上,则磁盘块就是它的最小组成单位,这时每个数据文件就是由多个磁盘块组成的)里所包含的数据,判断其中是否存在雇员信息。如果没有则读取下一个最小组成单位;如果有雇员信息,则读取其雇员号,判断该雇员号是否等于100,如果不是,则读取下一个最小组成单位。如果是,则返回该雇员信息。如此这般,直到该文件全都读取完毕为止。然后继续读取下一个数据文件,再做一遍这样的事情,直到读完所有的数据文件。这样才能找到所有雇员号为100的雇员信息。
很显然,这种方式是低效的。特别是如果数据文件很多,总数据量很大,比如上百GB,再加上并发用户数很多,很多用户都查找数据,那这种查找数据的方式是几乎不可能完成的任务。这里仅仅是举了一个查询的例子,如果再引入修改数据的话,那后果更不可想象。
Oracle数据库当然不会采用这种方式。为了更好地管理物理磁盘上的数据文件,Oracle引入了逻辑存储的概念。所谓逻辑存储的概念,可以理解为,Oracle把数据在物理文件里摆放的位置等信息都以数据行的形式存放在了相关的表里。
为了更有效地管理逻辑结构,Oracle对整个物理结构在逻辑上进行了分组。其分组结构如图1-2所示。
首先,最大的逻辑分组叫数据库(Database)。它由我们前面说到的三种关键文件组成。也就是数据文件、控制文件、联机日志文件的逻辑组合就叫做数据库。
其次,在数据库这个最大的逻辑组下,又可以划分多个较小的组,叫做表空间(Tablespace),表空间对应的物理结构就是数据文件。也就是说,我们可以把一个或多个数据文件在逻辑上组合起来,把它们在逻辑上组成一个表空间。为了便于理解,我们可以把表空间与数据文件的关系想象为文件系统中的文件夹与文件的关系。在文件系统中,我们可以把多个相关的文件共同放到某个文件夹下。对于表空间也是如此,比如,我们可能会按照业务逻辑来划分表空间,把销售类的数据存放到一个名为SALES_TS的表空间里,然后可以在该表空间下放置一个或多个物理的数据文件。一个表空间可以对应多个数据文件,而一个数据文件则只能对应一个表空间。
图1-2 Oracle存储结构
第三,在表空间下,我们在逻辑上又可以分成多个更小的逻辑组,叫做段(Segment)。所谓的段就是指我们比较熟悉的表、索引了。比如我们在销售类相关的SALES_TS表空间下可以创建多个与销售业务相关的表,每个表存放不同的销售数据,比如表A存放销售合同,表B存放销售明细记录等。我们知道,A和B里的数据实际是存放在数据文件里的。那么,在数据文件里有关A的所有物理数据对应的逻辑结构就叫做段A,表B则对应段B。一个段可以分布在多个数据文件里,比如我们有个很大的表,达到20GB。那么我们可以把这个大表分布到10个数据文件里,每个数据文件里分别放2GB的数据。当然,前提是该表段所能存放的数据文件必须都属于该表段所在的表空间。
第四,在段下,还可以划分成多个更小的逻辑组,叫做区(Extent)。Extent表示的是在逻辑上连续的一段空间,段的增加和减小都是以extent为单位。也就是说,当我们往一个表里不停地插入记录,导致该表段所占的物理空间变大,则在扩大段的时候,其增长的单位是一个或多个extent,不可能一次增加0.5个extent或3.6个extent。同样,当我们删除记录,导致表段缩小时,也是以extent为单位。由于extent是逻辑上连续的空间,所以一个extent不能跨越多个数据文件,否则如果一个extent分布在多个数据文件里,就不是连续的空间了。
最后,在extent下,还可以划分成多个最小的逻辑组,叫做数据块(Block)。数据块是不能再细分的逻辑组,它是Oracle里向操作系统发出一次I/O请求的最小单位。也就是一次I/O至少要获取一个数据块,当然也可以一次I/O获取多个数据块。但是不可能一次I/O获取0.5个数据块,也不可能一次I/O获取4.6个数据块。
在物理层面上,一个数据文件也是由许多个操作系统块组成的。那么Oracle里的一个数据块会对应多个操作系统块。在大部分的操作系统里,一个块为512个字节。而Oracle里的数据块的可选大小为2KB、4KB、8KB、16KB和32KB。因此,即使我们选择了最小的2KB作为一个数据块的大小,也会使得一个Oracle数据块包含4个操作系统块。这样主要是为了在进行I/O时效率能高一些,一次就获得多个操作系统块。
Oracle会把以上所描述的这些逻辑结构、逻辑结构之间的对应关系(比如某个表在某个表空间里,同时该表对应的段会由多个extent组成,而每个extent又由多个block组成)及逻辑结构与物理文件的对应关系(比如某个表的表空间包含哪些数据文件、该表对应的段所包含的extent以及extent所包含的block位于数据文件的什么地方等)存放在Oracle自己的核心数据表(这些表叫做数据字典)里。这样,当我们发出一条SQL语句,返回某个表里的数据时,Oracle就能够在数据字典里先确定表段所在的表空间,从而确定其所在的数据文件。然后,可以在数据字典里找到该表段所包含的所有的extent,进而可以找到每个extent所含有的数据块及数据块的地址。这样,Oracle就可以在数据字典里确定好该表段所含有的所有数据块,以及这些数据块对应到数据文件时的地址,从而根据这些数据块地址到数据文件里有的放矢地查找数据。