1.2.2 逻辑存储结构
达梦数据库的逻辑存储结构描述了数据库内部数据的组织和管理方式。达梦数据库为数据库中的所有对象分配逻辑空间,并存放在数据文件中。在达梦数据库内部,所有的数据文件组合在一起被划分到一个或多个表空间中,所有的数据库内部对象都存放在这些表空间中。同时,表空间被进一步划分为段、簇和页(也称为块)。这种细分可以使达梦数据库更加高效地控制磁盘空间的利用率。图1-3显示了逻辑存储结构之间的关系。
可以看出,在DM8中存储的层次结构可以表述为:系统由一个或多个表空间组成;每个表空间都由一个或多个数据文件组成;每个数据文件都由一个或多个簇组成;段是簇的上级逻辑单元,一个段可以跨多个数据文件;簇由磁盘上连续的页组成,一个簇总是在一个数据文件中;页是数据库中最小的分配单元,也是数据库中使用的最小的I/O单元。
1.表空间
在达梦数据库中,表空间由一个或多个数据文件组成。达梦数据库中的所有对象在逻辑上都存放在表空间中,而在物理上都存储在所属表空间的数据文件中。
在创建达梦数据库时,会自动创建 5 个表空间:SYSTEM 表空间、ROLL 表空间、MAIN表空间、TEMP表空间和HMAIN表空间。
图1-3 逻辑存储结构关系示意图
(1)SYSTEM表空间存放了有关达梦数据库的字典信息。
(2)ROLL表空间完全由达梦数据库自动维护,用户无须干预。该表空间用来存放事务运行过程中执行DML 操作之前的值,从而为访问该表空间的其他用户提供表空间数据的读一致性视图。
(3)MAIN 表空间在初始化达梦数据库的时候,会自动创建一个大小为128MB的数据文件MAIN.DBF。在创建用户时,如果没有指定默认表空间,则系统自动指定MAIN表空间为用户默认表空间。
(4)TEMP表空间完全由达梦数据库自动维护。当用户的SQL语句需要利用磁盘空间来完成某个操作时,达梦数据库会从 TEMP 表空间中分配临时段,如创建索引、无法在内存中完成的排序操作、SQL语句中间结果集及用户创建的临时表等都会用到TEMP表空间。
(5)HMAIN表空间属于HTS表空间,完全由达梦数据库自动维护,用户无须干涉。用户在创建 HFS 表空间时,在未指定 HTS 表空间的情况下,HMAIN 表空间充当默认HTS表空间。
每个用户都有一个默认的表空间。SYSSSO、SYSAUDITOR系统用户默认的表空间是SYSTEM表空间,SYSDBA用户默认的表空间为MAIN表空间,新创建的用户如果没有指定默认的表空间,则系统自动指定MAIN表空间为用户默认的表空间。用户在创建表的时候,当指定了存储表空间A,但和当前用户的默认表空间B不一致时,表存储在用户指定的表空间 A 中,并且在默认情况下,在这张表上建立的索引也将存储在表空间 A 中,但是用户默认的表空间是不变的,仍为表空间B。在一般情况下,建议用户自己创建一个表空间来存放业务数据,或者将数据存放在用户默认的表空间MAIN表空间中,而不是将数据存放在SYSTEM表空间中。
2.页
数据页(也称为数据块)是达梦数据库中最小的数据存储单元。页的大小对应物理存储空间上特定数量的存储字节,在达梦数据库中,页的大小可以为 4KB、8KB、16KB 或32KB,用户在创建数据库时可以指定页的大小,默认大小为8KB。一旦创建好了数据库,则在该数据库的整个生命周期内,页的大小都不能改变。图1-4显示了达梦数据库页的典型格式。
图1-4 达梦数据库页的典型格式
页头控制信息包含页类型、页地址等信息。页的中部存放了数据,为了更好地利用数据页,在数据页的尾部专门留出一部分空间用于存放行偏移数组。行偏移数组用于标识页上的空间占用情况,以便管理数据页自身的空间。
在绝大多数情况下,用户无须干预达梦数据库对数据页的管理。但是,达梦数据库还是提供了选项供用户选择,可以在某些情况下为用户提供更佳的数据处理性能。
FILLFACTOR是达梦数据库提供的一个与性能有关的数据页级存储参数,它指定一个数据页在初始化后插入数据时可以使用空间的最大百分比(100),该值在创建表/索引时可以指定。
设置FILLFACTOR参数的值,是为了指定数据页中可用空间百分比(FILLFACTOR)和可扩展空间百分比(100-FILLFACTOR)。可用空间用来执行更多的 INSERT 操作;可扩展空间用来为数据页保留一定的空间,以避免在今后的更新操作中增加列或修改变长列的长度时,引起数据页的频繁分裂。当插入的数据占据的数据页空间百分比小于FILLFACTOR时,允许数据插入该页;否则,将当前数据页中的数据分为两部分,一部分保留在当前数据页中,另一部分存入一个新数据页中。
对于DBA来说,在使用FILLFACTOR时应该在空间和性能之间进行权衡。为了充分利用空间,用户可以设置一个很大的FILLFACTOR值,如100,但是这可能会导致在后续更新数据时频繁引起数据页分裂,而导致需要大量的I/O操作。为了提高更新数据的性能,可以设置一个相对较小(但不是过小)的FILLFACTOR值,使得后续在执行更新操作时,可以尽量避免数据页分裂,提升I/O性能,但这是以牺牲空间利用率换取的性能提高。
3.簇
簇是数据页的上级逻辑单元,由同一个数据文件中16个或32个连续的数据页组成。在达梦数据库中,簇的大小由用户在创建数据库时指定,默认大小为16。假定某个数据文件大小为 32MB,页大小为 8KB,则共有 32MB/8KB/16=256 个簇,每个簇的大小均为8KB×16=128KB。和数据页的大小一样,一旦创建好数据库,此后该数据库簇的大小就不能改变了。
(1)分配数据簇。
当创建一个表/索引的时候,达梦数据库为表/索引的数据段分配至少一个簇,同时数据库会自动生成对应数量的空闲数据页,供后续操作使用。如果初始分配的簇中所有数据页都已经用完,或者新插入/更新数据需要更多的空间,达梦数据库将自动分配新的簇。在默认情况下,达梦数据库在创建表/索引时,初始分配1个簇,当初始分配的空间用完后,达梦数据库会自动扩展。
达梦数据库的表空间在为新的簇分配空闲空间时,首先在表空间中按文件从小到大的顺序在各个数据文件中查找可用的空闲簇,找到后进行分配;如果各数据文件中都没有空闲簇,则在各数据文件中查找足够的空闲空间,将需要的空间先进行格式化,然后进行分配;如果各数据文件的空闲空间也不够,则选择一个数据文件进行扩展。
(2)释放数据簇。
对于用户数据表空间,用户在将一个数据段对应的表/索引对象 DROP 之前,该表对应的数据段会保留至少1个簇不被回收到表空间中。在删除表/索引对象中的记录时,达梦数据库通过修改数据文件中的位图来释放簇,释放后的簇被视为空闲簇,可以供其他对象使用。当用户删除了表中的所有记录时,达梦数据库仍然会为该表保留1个或2个簇供后续使用。若用户使用DROP 语句来删除表/索引对象,则此表/索引对应的段及段中包含的簇全部收回,并供存储于此表空间中的其他模式对象使用。
对于TEMP表空间,达梦数据库会自动释放在执行SQL过程中产生的临时段,并将属于此临时段的簇空间还给TEMP表空间。需要注意的是,TEMP表空间文件在磁盘中所占大小并不会因此而缩减,用户可以通过系统函数SF_RESET_TEMP_TS来进行磁盘空间的清理。
对于ROLL表空间,达梦数据库将定期检查回滚段,并确定是否需要从回滚段中释放1个或多个簇。
4.段
段是簇的上级逻辑分区单元,段由一组簇组成。在同一个表空间中,段可以包含来自不同文件的簇,即一个段可以跨越不同的文件,而一个簇及该簇所包含的数据页则只能来自同一个文件,是连续的16个或32个数据页。由于簇的数量是按需分配的,因此数据段中的不同簇在磁盘上不一定连续。
(1)数据段。
段可以被定义成特定对象的数据结构,如表数据段或索引数据段。表中的数据以表数据段结构存储,索引中的数据以索引数据段结构存储。达梦数据库以簇为单位给每个数据段分配空间,在数据段的簇空间用完后,达梦数据库会给该段重新分配簇,段的分配和释放完全由达梦数据库自动完成,可以在创建表/索引时设置存储参数来决定数据段的簇如何分配。
当用户使用CREATE语句创建表/索引时,达梦数据库会创建相应的数据段。表/索引的存储参数用来决定对应数据段的簇如何分配,这些参数将影响与对象相关的数据段的存储与访问效率。对于分区表,每个分区使用单独的数据段来容纳所有数据;对于分区表上的非分区索引,使用一个索引数据段来容纳所有数据;而对于分区表上的分区索引,每个分区使用一个单独的索引数据段来容纳所有数据。表的数据段及与其相关的索引段不一定要存储在同一个表空间中,用户可以在创建表/索引时,指定不同的表空间存储参数。
(2)临时段。
在达梦数据库中,所有的临时段都创建在 TEMP 表空间中。这样可以分流磁盘设备的I/O,也可以减少由于在SYSTEM表空间或其他表空间中频繁创建临时数据段而造成的碎片。
在处理一个查询操作时,通常需要为 SQL 语句的解析与执行的中间结果准备临时空间。达梦数据库会自动地分配临时段的磁盘空间。例如,达梦数据库在进行排序操作时就可能需要使用临时段,当排序操作可以在内存中执行,或者设法利用索引就可以执行时,就不必创建临时段了。对于TEMP表空间及其索引,达梦数据库也会为它们分配临时段。临时段的分配和释放完全由系统自动控制,用户不能手动进行干预。
(3)回滚段。
达梦数据库在ROLL表空间的回滚段中保存了用于恢复数据库操作的信息。对于未提交事务,当执行回滚语句时,回滚记录被用来进行回滚变更。在数据库恢复阶段,回滚记录被用来进行任何未提交变更的回滚。在多个并发事务运行期间,回滚段还为用户提供数据读一致性,所有正在读取受影响行的用户将不会看到行中的任何变动,直到事务提交后发出新的查询。达梦数据库提供了全自动回滚管理机制来管理回滚信息和ROLL表空间,全自动回滚管理消除了管理回滚段的复杂性。此外,系统将尽可能保存回滚信息,以满足用户查询回滚信息的需要。事务被提交后,回滚数据不能再回滚或恢复,但是从数据读一致性的角度出发,长时间进行查询可能需要这些早期的回滚信息生成早期的数据页镜像,基于此,达梦数据库需要尽可能长时间地保存回滚信息。达梦数据库会收集回滚信息的使用情况,并根据统计结果对回滚信息的保存周期进行调整,数据库将回滚信息的保存周期设置为比系统中活动的最长查询时间稍长一些。