数据库管理系统是一种对内存申请和释放操作频率很高的软件,如果每次对内存的使用都使用操作系统函数来申请和释放,效率会比较低,加入自己的内存管理是 DBMS 所必须的。
通过内存管理会带来以下好处
····申请、释放内存效率更高
····能够有效地了解内存的使用情况
····易于发现内存泄漏和内存越界问题
DM 数据库的内存结构主要包括内存池、缓冲区、排序取、哈希区等。
内存池
DM Server 的内存池包括共享内存池和其他一些运行时内存池。
动态视图 V$MEM_POOL 详细记录了当前系统中所有的内存池的状态,可通过查询这个视图掌握内存的使用情况。
1、共享内存池
共享内存池是 DM Server 在启动时从操作系统申请的一大片内存。
在 DM Server 运行期间,经常会申请与释放小片内存,而向操作系统申请和释放内存需要发出系统调用,此操作可能会引起线程切换,降低运行效率。
采用共享内存池则可一次向操作系统申请一片较大内存,即为内存池,当数据库运行过程中需要申请内存时,可在共享内存池进行申请,用完再释放。
可以通过配置文件(dm.ini)来对共享内存池的大小进行设置,共享内存池的参数为 MEMORY_POOL,默认为 200M。
MEMORY_EXTENT_SIZE 参数指定共享内存池每次扩展的大小。
MEMORY_TARGET 参数指定共享内存池能扩展到的最大大小。
2、运行时内存池
除了共享内存池,DM Server 的一些功能模块在运行时还会使用自己的运行时内存池。
这些运行时内存池是从操作系统申请一片内存作为本地功能模块的内存池来使用,如会话内存池、虚拟机内存池等。
缓冲区
1、数据缓冲区
数据缓冲区是 DM Server 在将数据页写入磁盘之前以及从磁盘上读取数据页之后,数据页所存储的地方。
此缓冲区设定得太小,会导致缓冲页命中率低,磁盘IO频繁;设定得太大,会导致操作系统内存本身不够用。
系统启动时,首先根据配置的数据缓冲区大小向操作系统申请一片连续内存,并将其按数据页大小进行格式化,置入“自由”链中。
数据缓冲区存在三条链来管理被缓冲的数据页
····一条是“自由”链,用于存放目前尚未使用的内存数据页
····一条是“LRU”链,用于存放已被使用的内存数据页(包括未修改和已修改)
····一条是“脏”链,用于存放已被修改过的内存数据页
LRU 链能够较大程度地保证被淘汰的数据页在最近不会被使用,减少磁盘IO。
1)类别
DM Server 中有四种类型的数据缓冲区,分别是 NORMAL、KEEP、FAST、RECYCLE。
NORMAL 缓冲区主要是提供给系统处理的一些数据页,没有特定指定缓存区的情况下,默认缓存区为 NORMAL。
KEEP 缓冲区的特性是对缓冲区中的数据页很少或几乎不怎么淘汰出去,主要用于数据页需要经常处在内存中的应用。
RECYCLE 缓冲区供临时表空间使用。
FAST 缓冲区根据用户指定的 FAST_POOL_PAGES 大小由系统自动进行管理。
配置文件 dm.ini 中这些缓冲区的参数分别为:BUFFER(100MB)、KEEP(8MB)、RECYCLE(64MB)、FAST_POOL_PAGES(3000)。
括号中为默认值,分别对应 NORMAL缓冲区大小、KEEP缓冲区大小、RECYCLE缓冲区大小、FAST缓冲区数据页总数。
2)读多页
在需要进行大量 I/O 的应用中,DM 之前版本的策略是每次只读一页。
如果知道用户需要读取表的大量数据,当读取到第一页时,可以猜测用户可能需要读取这页的下一页,在这种情况下,一次性读取多页就可以减少 I/O 次数,从而提高了数据的查询、修改效率。
配置文件 dm.ini 中的 MULTI_PAGE_GET_NUM 参数控制每次读取的页数,默认值为 1 页。
2、日志缓冲区
日志缓冲区是用于存放重做日志的内存缓冲区。
为了避免由于直接的磁盘IO,而使系统性能受到影响,系统在运行过程中产生的日志并不会立即被写入磁盘,而是和数据页一样,先将其放置到日志缓冲区中。
不在数据缓冲区中缓存重做日志的原因
····重做日志的格式同数据页完全不一样,无法进行统一管理
····重做日志具备连续写的特点
····在逻辑上,写重做日志比数据页 IO 优先级更高
DM Server 提供了参数 RLOG_BUF_SIZE 对日志缓冲区大小进行控制。
日志缓冲区所占用的内存是从共享内存池中申请的,单位为页数量,且大小必须为 2 的 N 次方,否则采用默认大小 512 页。
3、字典缓冲区
字典缓冲区主要存储一些数据字典信息,如模式信息、表信息、列信息、触发器信息等。
每次对数据库的操作都会涉及到数据字典信息,访问数据字典信息的效率直接影响到相应的操作效率。
DM8 采用的是将部分数据字典信息加载到缓冲区中,并采用 LRU 算法进行字典信息的控制。
配置参数 DICT_BUF_SIZE 控制缓冲区的大小,默认大小为 5 M。
缓冲区配置得太大,会浪费内存空间;配置得太小,可能会频繁地进行淘汰。
4、SQL 缓冲区
SQL 缓冲区提供在执行 SQL 语句过程中所需要的内存,包括计划、SQL语句和结果集缓存。
配置参数 USE_PLN_POOL 控制是否需要计划重用,非0时启动计划重用,为0时禁用计划重用。
配置参数 CACHE_POOL_SIZE 设置 SQL 缓冲区的大小,默认值为 20M。
结果集缓存包括SQL查询结果集缓存和 DMSQL 程序函数结果集缓存,同时设置参数 RS_CAN_CACHE=1 且 USE_PLN_POOL 非0时,才会缓存结果集。
排序区
排序缓冲区提供数据排序所需的内存空间。
当用户执行 SQL 语句时,常常需要进行排序,所使用的内存就是排序缓冲区提供的。
在每次排序过程中,都首先申请内存,排序结束后再释放内存。
配置文件 dm.ini 中的参数 SORT_BUF_SIZE 用来指定排序缓冲区的大小。
哈希区
DM8 提供了为哈希连接而设定的缓冲区,不过该缓冲区是个虚拟缓冲区。
之所以说是虚拟缓冲区,因为系统没有真正创建特定属于哈希缓冲区的内存,是在进行哈希连接时,对排序的数据量进行了计算。
如果计算出的数据量大小超过了哈希缓冲区的大小,则使用 DM8 创新的外存哈希方式;
如果没有超过哈希缓冲区的大小,实际上使用的还是 VPOOL 内存池来进行哈希操作。
配置文件 dm.ini 中的参数 HJ_BUF_SIZE 控制缓冲区大小,建议保留默认值,或设置更大的值。