达梦数据库的大对象存取优化

日期: 2008-06-09 来源:TechTarget中国

  前言


  在数据库系统中,大对象往往是指这样一种类型的数据:这些数据的体积较大,占用的字节数在KB级或MB级,有的甚至达到GB级。对于DBMS来说,这些数据不具备结构性,只是单纯的字节流,存储时需一次性存入,读取时需一次性取出。日常生活中常见的图片、视频、音频以及大数据量大文本文件,都属于大对象数据的范畴。现有的各种关系型数据库管理系统也都提供了丰富的数据类型和完备的存取方法来管理大对象数据。毫无疑问,作为大型通用的数据库管理系统,达梦数据库为大对象的存储类型提供了全面的支持,在大对象数据的存储组织方式上采用B树结合从表的方式达到了很好的存取效率。然而,与Oracle的大对象存取效率相比,达梦数据库还有差距。为此,达梦数据库开发部门在近期对达梦数据库的存取策略进行了改进和优化。测试结果表明,优化后的达梦数据库在大对象存取效率方面与Oracle相比,要略微胜出。本文详细讨论了达梦数据库大对象存取优化的方法和思路,其目的主要有两个:(1)为使用达梦数据库的广大开发人员详细解释系统中大对象的存取方法,使他们能够基于达梦数据库开发出高效的应用系统;(2)抛砖引玉,向广大开发人员介绍达梦数据库,希望能够引起更多人的关注,获得更多的改进建议。


  1. 原有的大对象存取方法及其不足


  1.1 大对象存储组织方式及其不足


  不同于Oracle的簇存储方式,达梦数据库中,大对象数据的存储结构采用和普通数据一样的B树结构。对于每一个具有大对象字段的表(称之为主表),系统会为其设置一个从表,此表专门用来存储这个表的大对象数据。


  当往主表插入一条含大对象的记录时,系统将判断此记录的大小是否超过950字节,如果小于950字节,那么系统将这条记录直接插入到主表之中;反之,将这条记录中的大对象数据插入到从表之中。系统中同时规定,从表中每条记录的DATA字段的最大值为950个字节,如果一个大对象数据超过950B,那么需要将这个大对象划分成若干分片,每个数据分片表1中的其余三个字段组成一条从表记录插入到从表中。


  原有系统的这种做法简单易行,在基本的存储模块上增加了分片模块和重新组装模块即可实现了对大对象的存取。然而,这种做法有两个缺陷。


  1.从表记录中数据分片允许的最大值太小(为950个字节),导致一个体积较大的大对象在存储时,需要被分解成很多分片,在提取该大对象时,又需要重新组装众多分片。这些操作将耗费大量CPU时间。


  2.数据分片的最大值太小还导致了空间利用率过低。达梦数据库中,从表中的ROWID,COLID,FRAGID字段长度分别为8,2,4字节,每条物理记录另有控制信息26字节。这样,从表中每个数据分片需要有40个字节的数据来进行标识。假设需要往某主表插入100万个大小为1K的大对象,由于1KB > 950B,每个大对象都需要拆成两条记录插入到从表中。简单计算可以得出,存储每个大对象需要的额外字节为80B,100万个大对象,共1GB大约需要80MB额外空间,将近有10%的空间被用来标识大对象的数据分片,由此可以看出空间浪费较为严重。


  将数据分片的最大值设定为950字节是没有必要的。可以将这个值适当放大,减少将大对象分片重新组装分片消耗的时间,以及提高空间利用率。


  1.2 大对象的写日志机制及其不足


  达梦数据库中日志包括redo日志和undo日志。目前的系统中,在插入大对象数据时,redo日志的生成和处理方式和一般的数据插入是完全一样的,undo日志则进行了优化。下面首先对这两种机制进行简要的介绍。


  1.2.1 redo日志的处理


  达梦数据库中的redo日志记录了系统的对数据块的更新动作,我们可以按照redo日志,重做系统的每一步操作,保证系统的一致性。在系统正常工作时,每当往表中插入一条物理记录时,便会生成一条redo日志。在一个事务提交之前,系统将首先把系统缓冲区中的redo日志写入到磁盘中,然后再提交事务。通过这种方式,可以保证系统发生故障的时候,能够通过redo日志来恢复数据,保证系统数据的完整性和一致性。


  对于每一条要插入的物理记录,在将其插入到数据页之前都会构造一条对应的redo日志记录,redo日志记录的结构是一个六元组:


  (dbid, file_id, page_no, offset, len, new_data)


  其中,前4个参数是为了标识日志记录对应的物理记录在文件中所处的数据块的地址和块内偏移,参数new_data为正式数据,保存物理记录的记录头+记录体信息。参数len表示new_data数据的长度。


  系统在每次故障后重启时,使用上次运行时在日志文件中产生的redo日志记录,根据记录中dbid, file_id, page_no, offset四个字段的信息,找到记录对应的物理记录所在的数据块中的地址,并用new_data来覆盖这个物理记录。这样就可以保证系统故障前提交的事务对数据库的更新操作得到执行。


  1.2.2 undo日志的处理


  达梦数据库中,undo日志机制可以确保系统崩溃后重启时,系统能消除未提交事务对系统造成的影响。系统为每个事务分配有若干回滚段,事务对数据进行修改操作时会在回滚段中生产相应的回滚记录。如果事务成功提交,回滚段将被抛弃,如果事务被回滚,系统将利用回滚段将数据库中的数据恢复到事务开始前的状态。为了在系统故障或掉电等情况下,回滚段中的数据不会丢失,回滚段的数据记录在数据库文件而不是在内存中。


  系统对插入大对象时的undo日志生成方法进行了优化。对于普通数据,每往表中插入一条记录,系统会为记录生成回滚记录并保存到回滚段中;对于大对象数据,将大对象分片并插入到从表时,对于从表中具有同样rowid和colid的记录,仅对fragid = 0的记录生成回滚记录。在回滚时,根据回滚记录上rowid和colid,对从表的所有具有相同rowid和colid的记录进行回滚。显然,这种做法能够保证插入操作的正确回滚。


  综上所述,系统在往从表插入大对象数据时,redo日志的生成方法和普通数据是完全一样的,而undo日志则进行了优化。可以结合大对象数据插入的特点,参考undo日志在这方面的优化方法,来对大对象插入的redo日志生成机制进行优化。


  2.改进后的大对象存取方法


  2.1 大对象存储组织的优化


  原有系统将从表中大对象数据的体积的最大值限定为950字节是不合理的。可以考虑将这个值适当扩大。显然,从表记录允许存放的大对象体积越大,大对象存取的时间越短,空间利用率也越高。为此,可以考虑将从表中大对象体积的最大值放大到一个极限的位置。下面讨论这个极限值如何确定。


  达梦数据库对记录大小的限制是,系统内部任何物理记录的最大值不能超过块长一半。这种规定是为了确保一条物理记录只在一个物理块中,保证一个B树节点至少有两条物理记录,避免B树退化成链表结构。由此可知,从表中记录的大小不能超过块长一半。由于大对象从表的结构中,前三个字段的大小取值是固定的,因此,在从表记录大小不超过块长一半的前提下,能够精确地计算出从表记录中大对象体积的最大值。计算方法在此从略。显然,通过扩大从表记录中大对象体积的最大值,可以减少大对象分片和分片重组的时间,提高空间利用率。


  2.2 大对象写日志机制的优化


  分析写日志机制可以看出,插入大对象数据到从表中时,为每一条物理记录生成完整的redo日志记录是没有必要的。一种可行的优化思路是:


  1.在redo日志记录中只保存从表物理记录的rowid,colid和fraid字段,而不需要DATA字段既大对象数据。这种做法由于不用保存大对象数据,减少了redo日志的数据量,提高了写日志的速度,进而减少大对象数据插入所消耗的时间。


  2.记录插入过程中,保存了从表物理记录的数据块的块号,在大对象插入结束之后,事务提交之前,首先将插入操作生成的redo日志刷盘,然后将这些块刷盘。


  显然,这种redo日志优化方法将提高大对象插入的效率。下面从对事务的redo和undo操作两个方面来说明这种优化方法可以保证数据的正确性。


  1.对于在故障前已提交的事务,故障恢复时需要恢复而不是撤销事务对数据库的更新操作。在系统重启后,由于上次系统运行时往从表中插入的物理记录已经在事务提交之前被刷盘,所以此时(既系统重启后)从表中的记录都是完整和正确的,此时再使用redo日志记录来覆盖物理记录,只不过是将物理记录的前三个字段重新写入数据块而已,不会造成数据的丢失,虽然redo日志记录并没有记录大对象数据。


  2.对于在故障前未提交的事务,故障恢复时需要撤销事务对数据库的改动。此时,首先打开redo日志文件,从事务的开始点出发,正向扫描redo日志文件,使用redo日志记录中的rowid,colid和fraid替换表中的相应物理记录的这三个字段,直到故障发生的地方停止替换。然后再使用undo日志文件从故障发生的地方开始,反向利用回滚记录将具有与回滚记录相同rowid和colid的物理记录恢复到事务开始前的状态。这样,事务对从表的插入操作被成功撤销。


  由此可见,采用这种方法完全可以在系统发生故障后保证数据的正确性。这种优化方案是完全可行的。优化方案的具体做法如下:


  (1)修改redo日志生成机制。优化前的系统对从表的insert操作,为物理页上的所有改动生成日志记录并写入日志文件。优化后,RREC记录上只记录不包含分片数据的其他修改;


  (2)将大对象插入到从表时记录被修改的从表数据页号;


  (3)往从表插入一个大对象结束以后,将redo日志刷盘;


  (4)将redo日志刷盘后,将插入过程中修改的从表数据页全部刷盘。


  2.3 写日志机制优化的补充说明


  完成redo日志优化的优化工作后,在性能测试中我们发现,对redo日志生成机制进行优化并不能百分百地减少大对象插入的时间。当插入的大对象数据量较小时,优化后插入所消耗的时间反而要大于优化前。出现这种现象的原因是,优化后,每插入一个大对象数据都需要将从表中的相应数据页刷盘,刷盘将引起大量I/O操作,这将为日志生成增加额外的时间,数据量小的情况下,增加的时间将超过由于优化减少的时间。


  针对这个问题,我们设计了以下解决方案:


  (1)由应用系统开发人员来决定是否需要对大对象存储进行日志生成优化。如果需要存储的大对象数据量不是很大(建议值为小于100K),可以指定不进行日志优化,如果需要存储的大对象数据量比较大,可以指定进行日志优化。


  (2)系统中增加一个存储过程,用户可以调用此存储过程来指定是否对日志生成进行优化。


  (3)如果要插入的大对象数据类型是TEXT,系统默认不对日志进行优化,如果插入的大对象数据类型是BLOB,系统默认对日志进行优化。


  3.优化前后的测试结果


  最后给出优化前后的测试对比结果。由于本次优化工作的目标是缩小DM5.6相对于Oracle9i在大对象存取效率上的差异,因此首先给出优化前的DM5.6与Oracle9i的大对象存取速度对比结果,然后给出DM5.6优化前后的大对象存取速度对比结果。通过比较Oracle9i和优化后的DM5.6在在大对象存取速度上相对于优化前DM5.6的提升率,可以间接比较Oracle9i和优化后的DM5.6在大对象存取上的时间效率的差异。


  3.1 优化前DM与Oracle的大对象存取性能对比


  (1)相关配置说明


  硬件配置:


  CPU(个数) Pentium cpu 2.66GHz


  内存 1G


  操作系统 WINXP


  数据库版本:


  ORACLE ORACLE 9i


  DM 优化前的DM5.6


  内部参数:


  ORACLE 默认配置


  DM 默认配置


  测试数据:


  大对象数据采用大小为5M 的MPG格式文件。测试时,分别往数据库中插入1-64条,共5-320MB大对象数据。测试结果取三次的平均值。


  (2)ODBC方式插入大对象


  测试程序采用ODBC方式连接数据库,每插入一条数据便提交一次事务。首先给出优化前的DM5.6与Oracle9i的大对象插入速度对比结果。



  图1 优化前的DM5.6和Oracle9i的大对象插入速度对比


  (3)ODBC方式读取大对象


  接下来给出优化前的DM5.6与Oracle9i的大对象读取速度对比结果。



  图2 优化前的DM5.6和Oracle9i的大对象读取速度对比


  3.2 优化前后DM大对象存取性能对比


  (1)相关配置说明


  硬件配置:


  CPU(个数) 酷睿双核1.6GHz


  内存 1G


  操作系统 WINXP


  数据库版本:


  DM 优化前的DM5.6


  DM 优化后的DM5.6


  内部参数:


  ORACLE 默认配置


  DM 默认配置


  测试数据:


  在内存中生成1MB的大对象数据,测试时往数据库中插入1-500条大对象记录。测试结果取三次的平均值。


  (2)ODBC方式插入大对象


  测试程序采用ODBC方式连接数据库,每插入一条数据便提交一次事务。首先给出优化前后的DM5.6大对象插入速度对比结果。



  图3 优化前后的DM5.6大对象插入速度对比


  (3)ODBC方式读取大对象


  接下来给出优化前后的DM5.6大对象读取速度对比结果。



  图4 优化前后的DM5.6大对象读取速度对比


  3.3 结果分析


  通过四个对比测试可以得出以下结论:


  (1)优化前的DM5.6与Oracle9i在大对象插入速度上相差不大,平均来说,Oracle9i要快10%左右;但是在读取速度上,优化前的DM5.6要比Oracle9i慢接近1倍;


  (2)优化后的DM5.6在大对象插入速度有大幅提升,从图3可以看到,优化后的DM5.6要比优化前快约30%左右;在读取速度上,优化后的DM5.6比优化前快90%左右,接近1倍,基本上与Oracle9i的读取速度基本持平。


  最后的结论是,此次优化工作取得了令人满意的结果。

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

电子邮件地址不会被公开。 必填项已用*标注

敬请读者发表评论,本站保留删除与本文无关和不雅评论的权力。

相关推荐