数据库管理系统是一种对内存申请和释放操作频率很高的软件,若每次使用和释放内存时都要通过操作系统函数来操作,则效率会比较低,加入自己的内存管理是DBMS系统所必需的。通常内存管理系统会带来以下好处。
● 申请、释放内存效率更高。
● 能够有效地了解内存的使用情况。
● 易发现内存泄露和内存写越界的问题。
DM8管理系统的内存结构主要包括内存池、缓冲区、排序区、哈希区等。根据系统中子模块的不同功能,对内存进行上述结构划分,并采用不同的管理模式。
DMServer的内存池包括共享内存池和其他一些运行时内存池。
动态视图V$MEM_POOL详细记录了当前系统中所有内存池的状态,可通过查询这个动态视图掌握DMServer的内存使用情况。
共享内存池是DMServer在启动时从操作系统申请的一大片内存。在DMServer运行期间,经常会申请与释放小片内存,而向操作系统申请和释放内存时需要发出系统调用的请求,此时可能会引起线程切换,降低系统运行效率。采用共享内存池则可一次向操作系统申请一片较大内存,即内存池,当系统在运行过程中需要申请内存时,可在共享内存池内进行申请,当用完该内存时,再将其释放掉,即归还给共享内存池。
DM8系统管理员可以通过DMServer的配置文件(dm.ini)来对共享内存池的大小进行设置,共享内存池的参数为MEMORY_POOL,该参数配置默认为200MB。如果在运行时所需内存大于配置值,共享内存池也可进行自动扩展,INI参数MEMORY_EXTENT_SIZE指定了共享内存池每次扩展的大小,参数MEMORY_TARGET则指定了共享内存池能扩展到的最大大小。
除了共享内存池,DMServer的一些功能模块在运行时还会使用自己的运行时内存池。这些运行时内存池是从操作系统申请的一片内存,其会被作为本功能模块的内存池来使用,如会话内存池、虚拟机内存池等。
缓冲区是DM8存放中间数据的内存区域,主要包括数据缓冲区、日志缓冲区、字典缓冲区、SQL缓冲区等。
数据缓冲区是DMServer在将数据页写入磁盘之前以及从磁盘上读取数据页之后,存储数据页的区域。这是DMServer至关重要的内存区域之一,将其设定得太小,会导致缓冲页命中率低,磁盘I/O频繁;将其设定得太大,又会导致操作系统内存本身不够用。
系统启动时,首先根据配置的数据缓冲区大小向操作系统申请一片连续内存并将其按数据页大小进行格式化,并置入自由链。数据缓冲区中存在3条链来管理被缓冲的数据页,一条是自由链,用于存放目前尚未使用的内存数据页;一条是LRU链,用于存放已被使用的内存数据页(包括未修改和已修改);还有一条是脏链,用于存放已被修改过的内存数据页。
LRU链将系统当前使用的页按其最近是否被使用的顺序进行排序。这样,当数据缓冲区中的自由链被用完时,从LRU链中淘汰部分最近未使用的数据页,能够较大程度地保证被淘汰的数据页在最近不会被用到,减少I/O次数。
在系统运行过程中,通常存在一部分“非常热”(反复被访问)的数据页,将它们一直留在缓冲区中对系统性能会有好处。对于这部分数据页,数据缓冲区开辟了一个特定的区域来存放它们,以保证这些页不参与一般的淘汰机制,可以一直留在数据缓冲区中。
(1)类型。
DMServer中有4种类型的数据缓冲区,分别是NORMAL、KEEP、FAST和RECYCLE缓冲区。其中,用户可以在创建表空间或修改表空间时,指定表空间属于NORMAL缓冲区或KEEP缓冲区。RECYCLE缓冲区供临时表空间使用,FAST缓冲区根据用户指定的FAST_POOL_PAGES大小由系统自动进行管理,用户不能指定使用RECYCLE缓冲区和FAST缓冲区的表或表空间。
NORMAL缓冲区主要是提供给系统处理的一些数据页,在没有特别指定缓冲区的情况下,默认为NORMAL缓冲区;KEEP缓冲区的特性是很少或几乎不怎么淘汰缓冲区中的数据页,主要基于用户的应用是否需要经常处在内存当中,如果用户的应用需要经常处在内存当中,那么可以指定缓冲区为KEEP缓冲区。
DMServer提供了可以更改这些缓冲区大小的参数,用户可以根据自己的应用需求情况,指定dm.ini文件中的BUFFER(默认值为100MB)、KEEP(默认值为8MB)、RECYCLE(默认值为64MB)、FAST_POOL_PAGES(默认值为3000)值,这些值分别对应NORMAL缓冲区大小、KEEP缓冲区大小、RECYCLE缓冲区大小、FAST缓冲区数据页总数。
(2)读多页。
在需要进行大量I/O的应用当中,DM8之前版本的策略是每次只读取一页。如果知道用户需要读取表中的大量数据,那么当读取到第一页时,可以猜测用户可能需要读取这页的下一页,在这种情况下,一次性读取多页就可以减少I/O次数,从而提高数据的查询、修改效率。
DMServer提供了可以读取多页的参数,用户可以指定这些参数来调整数据库运行效率的最佳状态。在DM8的配置文件dm.ini中,可以指定参数MULTI_PAGE_GET_NUM值大小(默认值为16页),来控制每次读取的页数。
如果用户没有设置较合适的参数MULTI_PAGE_GET_NUM值大小,有时可能会给用户带来较差的读取效果。如果MULTI_PAGE_GET_NUM值太大,每次读取的页可能大多都不是以后要用到的数据页,这样不仅会增加I/O的读取次数,而且每次都会做一些无用的I/O,所以系统管理员需要衡量好自己的应用需求,给出最佳方案。
日志缓冲区是用于存放REDO日志的内存缓冲区。为了避免由于直接的磁盘I/O而使系统性能受到影响,系统在运行过程中产生的日志并不会被立即写入磁盘,而是和数据页一样,先将其放置到日志缓冲区中。那么为何不在数据缓冲区中缓存REDO日志,而要单独设立日志缓冲区呢?主要是基于以下原因。
● REDO日志的格式同数据页完全不一样,无法进行统一管理。
● REDO日志具备连续写的特点。
● 在逻辑上,写REDO日志比数据页I/O优先级更高。
DMServer提供参数RLOG_BUF_SIZE对日志缓冲区大小进行控制,日志缓冲区所占用的内存是从共享内存池中申请的,单位为页,且大小必须为2的N次方,否则采用系统默认大小(512页)。
字典缓冲区主要存储一些数据字典信息,如模式信息、表信息、列信息、触发器信息等。每次对数据库的操作都会涉及数据字典信息,访问数据字典信息的效率会直接影响到数据库相应的操作效率,如进行语句查询,就需要相应的表信息、列信息等,这些字典信息若都在缓冲区里,则直接从缓冲区中获取即可,否则需要I/O才能读取这些信息。
DM8将部分数据字典信息加载到缓冲区中,并采用LRU算法对字典信息进行控制。对于缓冲区大小的设置问题,如果设置太大,会浪费宝贵的内存空间,如果设置太小,可能会频繁地进行内存淘汰,该缓冲区配置参数为DICT_BUF_SIZE,配置大小默认为5MB。
DM8将部分数据字典信息加载到缓冲区中,那会影响效率吗?数据字典信息的访问存在热点现象,并不是所有的字典信息都会被频繁地访问,所以按需加载字典信息并不会影响到实际的运行效率。
但是如果在实际应用中涉及对分区数较多的水平分区表的访问,如上千个分区,那么就需要适当调大DICT_BUF_SIZE参数值。
SQL缓冲区提供在执行SQL语句过程中所需要的内存,包括计划、SQL语句和结果集缓存。
很多应用都存在反复执行相同SQL语句的情况,此时可以使用缓冲区保存这些语句和它们的执行计划,这就是计划重用。这样带来的好处是提高了SQL语句的执行效率,但同时也给内存增加了压力。
DMServer在配置文件dm.ini中提供了参数来控制是否需要计划重用,参数为USE_PLN_POOL,当将该参数指定为非0时,启动计划重用;当将其指定为0时,禁止计划重用。DM8同时还提供了参数CACHE_POOL_SIZE(单位为MB)来改变SQL缓冲区大小,系统管理员可以设置该值以满足应用需求,默认值为20MB。
结果集缓存包括SQL查询结果集缓存和DMSQL程序函数结果集缓存,在dm.ini参数文件中同时设置参数RS_CAN_CACHE=1且USE_PLN_POOL非0时,DM8服务器才会缓存结果集。DM8还提供了一些手动设置结果集缓存的方法,具体可参看《DM8系统管理员手册》。
客户端结果集也可以被缓存,但需要在配置文件dm_svc.conf中设置参数,配置文件中的参数设置如下。
同时,在服务器端使用dm.ini参数文件中的CLT_CACHE_TABLES参数来设置哪些表的结果集需要缓存。另外,FIRST_ROWS参数表示当查询的结果达到该行数时,就返回结果,不再继续查询,除非用户向服务器发送一个FETCH命令。这个参数也被用于配置客户端缓存,仅当结果集的行数不超过FIRST_ROWS时,该结果集才可能被客户端缓存。
排序区提供数据排序所需要的内存空间。当用户执行SQL语句时,常常需要进行排序,所使用的内存就是排序区提供的。在每次排序过程中,首先要申请内存,排序结束后再释放内存。
DMServer提供了参数来指定排序缓冲区的大小,在参数SORT_BUF_SIZE在DM8的配置文件dm.ini中,系统管理员可以设置其大小以满足实际需求,由于该值是由系统内部排序算法和排序数据结构决定的,建议使用默认值2MB。
DM8提供了为哈希连接而设定的缓冲区,不过该缓冲区是一个虚拟缓冲区。之所以说是虚拟缓冲区,是因为系统没有真正创建特定属于哈希缓冲区的内存,而是在进行哈希连接时,对排序的数据量进行了计算。若计算出的数据量大小超过了哈希缓冲区的大小,则使用DM8创新的外存哈希方式;若没有超过哈希缓冲区的大小,则实际上还是使用VPOOL内存池来进行哈希操作。
DMServer在dm.ini中提供了参数HJ_BUF_SIZE来进行控制,该值的大小可能会限制哈希连接的效率,因此建议保持默认值,或设置为更大的值。
除了提供HJ_BUF_SIZE参数,DMServer还提供了创建哈希表个数的初始化参数,其中,HAGR_HASH_SIZE表示处理聚集函数时创建哈希表的个数,建议保持默认值为100000。