达梦数据库管理系统的内存结构主要包括内存池、缓冲区、排序缓冲区、哈希缓冲区等。
达梦数据库的内存池包括共享内存池和运行时内存池。
共享内存池是数据库实例在启动时从操作系统申请的一大片内存。在数据库实例的运行期间,经常会申请与释放小片内存。而直接向操作系统申请和释放内存时需要发出系统调用,此时可能会引起线程切换,降低系统运行效率。于是达梦数据库采用了共享内存池的方式:一次向操作系统申请一片较大内存,作为共享内存池。当系统在运行过程中需要申请小片内存时,可在共享内存池内进行申请,当用完该内存时,再释放掉,即归还给共享内存池。
设置共享内存池初始值的参数为MEMORY_POOL,该参数为静态参数,默认值为500MB。共享内存池在运行期间会根据需要进行自动扩展,静态参数MEMORY_EXTENT_SIZE指定了共享内存池每次扩展的大小。动态参数MEMORY_TARGET则指定了共享内存池大小的控制目标值(0表示不限制),超过目标值的内存空间会在系统空闲时进行释放。
注意 Oracle数据库的内存参数MEMORY_TARGET控制的是数据库实例占用的全部内存总量(SGA+PGA),是数据库实例能够使用的内存的最大值。而达梦数据库的MEMORY_TARGET参数仅仅是共享内存池(类似于Oracle数据库实例中的SHARED_POOL_SIZE)内存分配参数。而且达梦数据库的这个参数只是目标值,并不是最大值,运行期间实际内存使用量可以大于这个参数值。只是在数据库实例空闲时逐步释放超出的部分。
达梦数据库中与Oracle数据库的MEMORY_TARGET参数相似的参数是MAX_OS_MEMORY。这个参数设置的是整个数据库实例使用的内存空间占操作系统总共内存空间的比例,参数值范围为40~100,默认值为100(不限制)。
除了共享内存池,达梦数据库实例的一些功能模块在运行时还会使用自己的运行时内存池。这些运行时内存池是从操作系统申请一片内存作为本功能模块的内存池来使用,如会话内存池等。类似于Oracle数据库的PGA(Program Global Area,程序全局区)。
数据缓冲区是用来缓存从数据文件中读取的数据页。用户进程在操作数据资源时,如果在数据缓存区内找到了所需的数据,就可以直接从内存中访问数据。如果用户进程不能在数据缓存区中找到所需的数据,则需要从磁盘中的数据文件里将相应的数据页复制到缓存区中才能进行访问。因此,缓存命中时的数据访问速度远远高于缓存失败时的速度。缓存命中率是衡量数据库运行性能的重要指标。
达梦数据库中有四种类型的数据缓冲区,分别是NORMAL、KEEP、FAST和RECYCLE。在创建表空间或修改表空间时,可以指定表空间属于NORMAL或KEEP缓冲区。RECYCLE缓冲区供临时表空间使用,FAST缓冲区根据用户指定的FAST_POOL_PAGES大小由系统自动进行管理,用户不能指定使用RECYCLE和FAST缓冲区的表或表空间。
NORMAL缓冲区主要是提供给系统处理的一些数据页,没有特定指定缓冲区的情况下,默认缓冲区为NORMAL;KEEP的特性对缓冲区中的数据页很少或几乎不怎么淘汰出去,主要针对用户的应用是否需要经常处在内存当中,如果是这种情况,可以指定缓冲区为KEEP。
在配置文件dm.ini修改相应的参数:BUFFER(默认值为1000MB)、KEEP(默认值为8MB)、RECYCLE(默认值为300MB)、FAST_POOL_PAGES(默认值为3000)。
达梦数据库实例默认I/O操作每次只读取一个数据页,在读取数据较多的情况下,就会执行多次I/O操作,读取效率较低。如果一次I/O读取多页就可以减少I/O次数,从而提高效率。因此达梦数据库允许用户修改每次I/O操作读取的数据页的数量,对应的参数是MULTI_PAGE_GET_NUM,有效值范围为1~64,该参数是静态参数,修改后需要重启实例生效。
注意 MULTI_PAGE_GET_NUM 的值并不是越大越好,如果设置过大,会导致读取大量的无关数据页,反而降低效率,浪费缓冲区空间。此外,在使用数据库加密或者启用SSD缓冲区(SSD_BUF_SIZE>0)的情况下,不支持多页读取,该参数无效。
数据库系统在运行过程中产生的redo日志并不会立即写入磁盘,而先存放到日志缓冲区中,然后分别由dm_redolog_thd线程、dm_rsyswrk_thd线程刷新到联机日志文件、归档日志文件中。
redo日志所占用的内存是从共享内存池中申请的,并不在数据缓冲区中。日志缓冲区与数据缓冲区分开设立主要是基于以下原因。
(1)重做日志的格式同数据页完全不一样,无法进行统一管理。
(2)磁盘上的重做日志是连续存放的,数据页则是随机存放。
(3)写重做日志比写数据页的优先级更高,也更频繁。
达梦数据库提供了两个参数对日志缓冲区进行控制:RLOG_BUF_SIZE(单个日志缓冲区最大页数,默认值为1024),RLOG_POOL_SIZE(日志缓冲池空间,单位为MB,默认为256MB,取值范围为1~4096)。
SQL缓冲区提供在执行SQL语句过程中所需要的内存,包括执行计划、SQL语句和结果集缓存。
很多应用当中都存在反复执行相同SQL语句的情况,此时可以使用缓冲区保存这些语句和它们的执行计划,同样的SQL语句可以重用之前的执行计划。这样带来的好处是提高了SQL语句执行效率,但同时给内存增加了压力。
达梦数据库在配置文件dm.ini提供了参数来支持是否需要计划重用,参数为USE_PLN_POOL,当指定为非0时,则启动计划重用;为0时,则禁止计划重用。达梦数据库同时还提供了参数CACHE_POOL_SIZE(单位为MB)来改变SQL语句缓冲区大小,系统管理员可以设置该值以满足应用需求,默认值为100MB。
结果集缓存包括SQL语句查询结果集缓存和DMSQL程序函数结果集缓存。在INI参数文件中同时设置参数RS_CAN_CACHE=1且USE_PLN_POOL非0时,数据库才会缓存结果集。
客户端结果集也可以缓存,但需要在配置文件dm_svc.conf中设置参数:
ENABLE_RS_CACHE = (1)表示启用缓存。
RS_CACHE_SIZE = (100)表示缓存区的大小为100MB,可配置为1~65535。
RS_REFRESH_FREQ = (30)表示每30秒检查缓存的有效性,如果失效,自动重查;0表示不检查。
同时在服务器端使用INI参数文件中的CLT_CACHE_TABLES参数设置哪些表的结果集需要缓存。另外,FIRST_ROWS参数表示当查询的结果达到该行数时,就返回结果,不再继续查询,除非用户向服务器发一个FETCH命令。这个参数也用于客户端缓存的配置,仅当结果集的行数不超过FIRST_ROWS时,该结果集才可能被客户端缓存。
字典缓冲区主要存储一些数据字典信息,如模式信息、表信息、列信息、索引信息等。数据库的所有操作都会涉及数据字典,因此读取数据字典的效率直接影响到数据库实例的运行效率。将数据字典信息缓存到内存中,可以有效地减少磁盘I/O,提高数据库运行效率。
达梦数据库采用的是将部分数据字典信息加载到缓冲区中,并采用LRU算法进行数据置换。缓冲区最大配置参数为DICT_BUF_SIZE,默认的配置大小为50(MB),取值范围为1~2048。
达梦数据库提供了两个视图查看字典缓冲区的情况。
(1)V$DICT_CACHE_ITEM,显示字典缓存中的字典对象信息。
(2)V$DICT_CACHE,显示字典缓存信息。
排序缓冲区提供数据排序所需要的内存空间。当用户执行的SQL语句进行排序操作时,所使用的内存就是排序缓冲区提供的。
达梦数据库在配置文件dm.ini中提供了设置排序缓冲区的大小的参数SORT_BUF_SIZE,该值由系统内部排序算法和排序数据结构决定,默认值为20MB,有效值范围为1~2048。
达梦数据库提供了为哈希连接而设定的缓冲区,不过系统并没有真正创建特定属于哈希缓冲区的内存,而是在进行哈希连接时,对排序的数据量进行计算。如果计算出的数据量大小超过了哈希缓冲区的大小,则使用达梦数据库创新的外存哈希方式;如果没有超过哈希缓冲区的大小,实际上还是使用内存池来进行哈希操作。
达梦数据库在配置文件dm.ini中提供了参数HJ_BUF_SIZE来进行控制,该参数默认值为50MB。由于该值的大小可能会限制哈希连接的效率,所以建议保持默认值,或设置为更大的值。
此外,达梦数据库还提供了创建哈希表个数的初始化参数,其中,HAGR_HASH_SIZE表示处理聚集函数时创建哈希表的个数,默认值为100000。