王建军 赵银刚 刘高川
摘要:针对目前地震前兆Oracle数据库存在的存储空间大、交换速度慢、读写速度慢等问题,分别用Bzip2,Gzip,GzipIO这3种压缩算法对Clob和Blob的壓缩和未压缩数据进行读写和交换速度测试,使用直接读取、分段读取、分段+线程池读取3种方法进行了读库速度测试。结果表明:①无论在存储、交换还是读写速度方面Blob均优于Clob;②Blob+Gzip为地震前兆分秒数据的“最佳”存储结构,读写和交换速度有大幅度提升,数据库整体容量降至目前的7%(或更少),秒数据的交换速率至少是目前的789倍;③最简单且被软件开发者广泛使用的直接读取方法读库效率较差,分段+线程池技术无论在Clob还是Blob、压缩还是未压缩时都表现出较高的读库效率,给LOB数据读取速度带来飞跃式的提升。
关键词:Oracle;LOB;数据压缩;交换效率;访问效率
中图分类号:P31573 文献标识码:A 文章编号:1000-0666(2019)03-0447-07
0 引言
随着信息化社会的发展,存储、传输和处理急剧增长的海量信息的压力越来越大。为了节省信息的存储空间和提高信息的传输效率,数据压缩作为解决海量信息存储和传输的支持技术受到极大重视(郑翠芳,2011)。数据压缩技术一般分为有损压缩和无损压缩。无损压缩是指重构压缩数据(还原、解压缩)与原数据必须完全相同,适用于要求重构信号与原始信号完全一致的场合(李雷定等,2009;郑翠芳,2011)。压缩算法必须能够提供较高的数据压缩率以支持实时数据库海量存储的特点,压缩和解压缩两个过程都必须具有较好的速度性能(刘红霞,牛富丽,2010)。
Bzip2是基于Burrows-Wheeler变换(BWT)的无损压缩算法,是一种不依赖于数据内部重复性的变换方法,它能将数据中相同的字符有效地聚集到一起,为进一步压缩创造条件(李冰等,2015;Seward,2002,2007)。它能够把普通的数据压缩至10%~15%,压缩和解压效率都非常高,按照开源软件协议在其网站上可下载完整的C,Java,C#源代码及相应的dll接口文件。它因为较高的压缩比和速度性能在国外被广泛应用(Gilchrist,2008;Pankratius et al,2009;Mccool et al,2012;Salazar,Sánchez,2017),但在国内的应用仍然偏少(李冰等,2015)。数据压缩算法有Bzip2和Gzip两种,Net的SystemIOCompression提供另一种Gzip压缩算法,本文简称为GzipIO。
2007年底地震前兆台网“十五”系统正式建成并投入运行,该软件系统是一个分层的4级互联互通分布式系统,由台站、省局、国家中心和学科中心4级构成。为便于各级数据交换,全国采用统一的数据库管理系统(Oracle10g)和统一的数据库表结构(周克昌等,2009,2010;刘高川,2008)。软件系统主要有2个:管理系统(B/S架构,服务器运行)和处理系统(C/S架构,客户端PC机运行),前者每天定时将台站数据逐级交换至省局、国家中心和学科中心(刘高川,2008),后者负责每天的数据预处理和产品数据计算。
中国地震台网中心前兆台网部是全国地震前兆数据的汇集中心,同时也是容量最大的前兆数据库。截至2018年8月,该数据库中存储了3 328套观测仪器(秒采样仪器364套,分采样仪器2 126套,时、日采样仪器838套)的产出数据,数据库总量约8 000 GB,目前仍在以每年约800 GB的速度递增,其中时间分辨率为分和秒的数据(以下简称为分秒数据)总量占到数据库总是的95%以上。因为所有分秒数据全部采用Clob+ASCII未压缩的存储格式,数据库出现了存储空间大、交换速度慢、读写速度慢、运维困难等问题。如“处理系统”远程读取FHDZ-M15地磁仪器1天6个要素的秒采样数据需要约4 min;中国地震台网中心前兆台网部(8 000 GB)冷备份到另一台服务器需要连续拷贝10天左右,这10天必须关闭数据库并停止所有服务,这种冷备份方式显然不实用;而热备份系统(由地震系统自主研发)因为软件原因只能对应一台服务器,如果主库和备库同时出现问题导致数据丢失,结果将是灾难性的。
Oracle数据库中,Clob和Blob(简称LOB)是2个典型的大对象数据存储结构,在各级数据库中都有广泛使用。Clob只能存储单字节字符数据,多用于存储长文本数据;Blob用于存储无结构的二进制数据,主要存储图像、视频、音频及Word文档等带格式数据(张静,王永敏,2011)。为提高地震前兆数据库的存取效率,国内地震行业学者分别进行了如下研究:姚运生等(2006)提出把一串观测数据以二进制存储为一个记录的新的数据库表结构;李井冈等(2008)对比了Clob和Blob的存取速度,发现Blob具有更高的效率,主要原因如下:一是二进制数据比字符串型数据存取快;二是Blob类型占用更少的空间,网络传输快;刘坚等(2009)把LZMA压缩算法封装成API动态链接库,调用接口函数压缩大数据后保存至Blob字段,调用数据时将数据解压缩还原,不仅节省了数据库的磁盘空间,同时也提高了数据存取效率。
本文基于NET开发平台,分别使用Bzip2,Gzip,GzipIO这3种压缩算法对Clob和Blob的压缩和未压缩数据进行了读写速度、交换速度测试和比较,使用直接读取、分段读取、分段+线程池读取3种技术进行了读库速度测试,对每种压缩算法和读库方法的优缺点进行了归纳和总结,以此检验适用于地震前兆数据库的“最佳”压缩算法和读库方法。
1 测试数据和研究方法
11 测试数据选取
本文选用的测试数据全部为2009年1月1日至兰州FHDZ-M15地磁仪器记录的共31天的6个要素分秒数据。该仪器为秒采样,每个要素每天包括86 400个秒采样数据,分数据由秒采样数据通过高斯滤波计算得到,每个要素每天包括1 440个分数据。
本文测试选用的本地服务器位于甘肃省地震局信息机房,远程服务器位于中国地震局地球物理研究所信息机房,本地和远程的测试数据和表结构完全相同。测试软件为Net开发平台编写的客户端软件(运行在办公室的PC机上)。
地震前兆数据库中分秒数据的表结构见表1,观测数据用Clob+ASCII未压缩的存储格式,每套仪器每个要素每天一条记录。
12 LOB数据压缩和解压缩方法
Net中引用Bzip2提供的接口文件ICSharp CodeSharpZipLibdll后,通过命名空间ICSharpCodeSharpZipLib,调用BZip2OutputStream和BZip2InputStream分别完成Bzip2压缩和解压过程,调用GzipOutputStream和GzipInputStream分别完成Gzip压缩和解压过程,通过调用SystemIO CompressionGzipStream分别完成GzipIO压缩和解压过程。
13 数据库连接和LOB读写方法
Net使用ADONET完成数据库访问,OracleConnection進行数据库连接,OracleDataAdapter和DataTable完成LOB数据读取和暂存,OracleCommand完成LOB数据写入。
14 3种LOB读库方法
(1)直接读取:对软件开发者而言,LOB数据最简单最常用的读库方法就是直接使用Select LobName读取。
(2)分段读取:无论Clob还是Blob都可以使用Oracle自带的DBMS_LOB包中的substr函数来分段读取数据,即DBMS_LOBsubstr(lobName,n,pos),lobName为Lob字段名,n为读取的字节数,pos为读取的起始位置。分段读取时Clob每次可读取的最大长度为4 000字节,Blob为2 000字节,因此必须循环多次执行,每次循环都要重新设置读取的起始位置(pos),循环结束后需要把同一条记录的LOB数据按先后顺序拼接起来。
(3)分段+线程池读取:NET的ThreadPool类提供线程池管理,将分段读取的SQL语句依次放入线程池中,可以实现分段读取并行执行(多个线程同时读取)。图1为该方法读库流程图,使用时还需要编写一个单独的子线程类,该类中需要创建新的数据库连接,执行分段读取的SQL语句;任务全部添加进线程池后,还需要一个while循环,判断所有线程全部执行结束后才能退出循环执行后续操作。
2 LOB数据压缩和交换速度测试
21 LOB数据压缩测试
分别使用Bzip2,Gzip,GzipIO这3种压缩算法,对兰州FHDZ-M15地磁仪器产出的2009年1月分秒数据进行压缩测试。表2显示平均每条记录的压缩比,无论分或秒数据,Bzip2的压缩比最高,Gzip次之,GzipIO最低;Bzip2压缩后每条记录的容量最小,意味着占用更小的存储空间;但其压缩和解压时间最长,远高于其他2种算法,意味着读库(解压)和写库(压缩)消耗的时间更长。Gzip的压缩时间大概是GzipIO的25倍,二者的解压时间相差很小,但分秒数据的二进制压缩比分别提高了5%和3%。
22 LOB数据交换速度测试
目前地震前兆管理系统软件在数据交换时采用的是“dbLink+Insert”技术,数据交换的核心命令为insert into XX from XX@dbLinkName,dbLinkName为远程数据库的dbLink。根据目前的地震前兆数据交换机制,交换过程中无需解析LOB数据,因此压缩和解压效率对交换速度没有影响,能影响到交换速度的只是每条记录的容量大小。登录远程(北京)数据库后直接运行该交换命令,其执行时间作为实际交换时间,即平均每条记录由本地(兰州)传输到远程(北京)的时间。兰州FHDZ-M15地磁仪器2009年1月所有分秒数据平均每条记录的数据交换速度测试结果见表3,预估交换倍率=“Clob未压缩”容量/其他容量,实际交换倍率=“Clob未压缩”交换时间/其他交换时间。
由表3可见,无论Clob还是Blob,3种压缩结构的实际交倍率都没有预估交换倍率高,秒数据Blob压缩的实际交换倍率有7~9倍的提升,而分数据的实际交换倍率提升幅度很小;秒数据Blob和Clob这2种未压缩结构相比,在存储容量完全相同的情况下实际交换倍率却有184倍的提升。
3 LOB数据读写速度测试
31 3种压缩算法的读写速度测试
使用直接读取方法对Blob和Clob的4种存储结构(3种压缩+未压缩)进行读写速度测试,由表4可见:①就写库速度而言,无论Clob还是Blob速度最快是GzipIO,Gzip次之,两者相差极小,Bzip2因为压缩时间长导致本地写库速度远慢于其它;②就读取速度而言,Clob中Bzip2最快,Blob中Gzip最快,即便偶有慢于其他方法的现象,读取速度仍与最快速度相差最小;③对同一种压缩或未压缩结构,2种LOB类型的写库速度基本相当,但Blob的读库速度远优于Clob。
32 3种LOB读库方法的读取速度测试
分别使用3种LOB读库方法对压缩和未压缩结构进行读库速度测试,测试结果见表5:①直接读取方法在Clob未压缩中读取效率最差,远慢于其他2种方法;在Blob中除了秒数据1天本地读取速度较快外,其他读取效率最差,并且随着读取天数的增加,与分段+线程池方法的读取速度差距增大。②分段读取方法在Clob未压缩中相对直接读取速度有大幅度提升,但在Blob秒数据读取时表现不稳定,频繁出现读取时间远高于其它方法现象。③分段+线程池方法在Clob未压缩中读取速度最快,远优于其他2种方法,在Blob中虽偶有略慢于其它方法,仍与读取最快速度相差极小。④无论哪种读库方法,Gzip的读取速度都优于GzipIO。
相对而言,与其他2种方法相比,无论在Clob还是Blob,压缩还是未压缩,分段+线程池方法都能表现出最高的读库效率,尤其在Clob未压缩的读取速度有飞跃式的提升。Blob+Gzip的存储结构结合分段+线程池读库方法,可使地震前兆数据库的读库性能达到“最佳”。
4 讨论
实验表明Blob在存储性能上优于Clob,但Clob字段在提高长文本数据的检索速度方面存在优势(张静,王永敏,2011)。上述测试结果再次验证了Blob无论在存储、交换还是读写速度方面均优于Clob,但Clob+ASCII未压缩格式可以使用DBMS_ LOBsubstr函数读取部分数据(由分隔符反推每个数据的起始位置),此时的读取速度远优于整体读取,而Blob因为采取二进制存储而无法做到。对地震前兆数据库而言,读取部分数据的情况极少,大量的实际应用是整体读取(数据处理、绘图、下载等)。
最佳的压缩算法为压缩比最高、压缩和解压速度最快的算法,但实际中很难同时满足这样的要求。Bzip2的压缩比最高,但压缩和解压时间偏长,Gzip和GzipIO的压缩和解压时间短但压缩比略低。压缩和解压2个过程都必须具有较好的速度性能,这2个问题的解是相互矛盾的,我们就是要找到两者的平衡点,使其达到最优性能(刘红霞,牛富丽,2010)。
从表2,4和5的测试结果来看,3种压缩算法的压缩比差异导致平均每条记录的容量不一样,进而导致读写速度与压缩算法相关,表4和5的读写时间包括了压缩和解压时间,以此来反映压缩和解压速度。如果单从分秒数据的读写速度来考虑,Gzip和GzipIO优于Bzip2;Gzip和GzipIO相比,前者读库速度占优,后者写库速度占优,但Gzip的分秒数据压缩比高出GzipIO的5%和3%,将为磁盘节省更多的存储空间,数据交换速度将更快。
对地震前兆数据库而言,如果采用Blob+Gzip存储结构,数据库整体容量降至目前的7%(或更少),分秒数据读写速度有大幅度提升,秒数据交换速度至少是目前的789倍,台站数据可在最短时间内交换到5个前兆学科中心,从而让地震前兆数据发挥更为重要的时效性。
直接读取方法是最简单且被软件开发者使用最广泛的一种读库方法,但其读库效率较差。分段读取方法在Clob秒数据读取时平均循环150次(58851 Kb/4 000 b)才能读取一条记录,但读取速度却远优于直接读取,这应该是它所使用的Substr函数将大对象转换为Varchar2类型所致;Clob每次可读取的最大长度为4 000字节,Blob为2 000字节,在记录容量相同的情况下,Blob的循环次数是Clob的2倍,部分程度会导致Blob读取效率下降,这应该是它在Blob秒数据读取时表现不稳定,频繁出现读取时间远高于其他2种方法的根本原因。分段+线程池方法采用的是多线程并行读取技术,恰好弥补了这个不足,无论在Clob还是Blob、压缩还是未压缩时都表现出了较高的读库效率。
分段+线程池方法的缺点是读取过程中要消耗大量的数据库连接,数据库中必须设置有足够的连接数量(Open_Cursors)。NET中线程池管理具有每个可用处理器最多25个线程的默认限制,笔者在大量的读库测试中监测到的最大并发线程数只有19个,虽然在LOB读取时同时开启的线程总数可能高达200~300个,但实际上并发读取的最多只能有25个,其他线程全部处于等待状态。全国地震前兆数据库目前的Open_Cursors总数全部设置为30 000,按此推算可同时支持1 200人使用该方法并发读库,而且数据库访问必须在地震行业专网下,该配置足以支持“分段+线程池”方法在地震系统内部使用。
2015年10月,笔者利用Bzip2算法完成地磁学科中心数据库Ceabak表空间压缩,并提供给全国分析预报人员访问,所有分秒数据全部改用Blob+Bzip2压缩结构,压缩前地磁数据库总量约为3 500 GB,压缩后为126 GB,整体压缩比约为36%,该压缩数据库运行至今未出现任何问题。2015年10月,笔者在全国地磁台网数据处理软件V20156版本中将Clob读取改用分段读取方法(之前版本采用直接读取方法),2017年11月在V20172版本中将Clob和Blob全部改用分段+线程池读库技术,这2次升级后该软件读库速度均有大幅度提升,目前每天的用户总数约200人次,台站人员利用该软件协助地磁学科进行分秒数据远程监控也得已实现。
5 结论
本文选取2009年1月1日至31日兰州FHDZ-M15地磁仪器的6个要素分秒数据,分别用Bzip2,Gzip,GzipIO压缩算法进行压缩测试,用Clob和Blob进行了读写和交换速度测试,并使用3种读库方法进行了读库速度测试,主要结论如下:Blob无论在存储、交换还是读写速度方面均优于Clob,但Clob在长文本数据检索方面存在优势;Blob+Gzip为地震前兆数据库分秒数据的“最佳”存储结构,读写速度均有大幅度提升,数据库整体容量至少可降至目前的7%(或更少),秒数据交换速率至少是目前的789倍,台站数据可在最短时间内交换到5个前兆学科中心,从而让地震前兆数据发挥更为重要的时效性;最简单且被软件开发者使用最广泛的直接读取方法读库效率较差,分段读取方法在Clob中远优于直接读取,但在Blob中表现不稳定,分段+线程池技术无论在Clob还是Blob、压缩还是未压缩时都表现出较高的读库效率,给LOB数据的读取速度带来飞跃式的提升。
本文所有测试数据全部来自国家地磁台网中心,在此表示诚挚的感谢!
参考文献:
李冰,龙冰洁,刘勇2015一种基于后缀排序快速实现Burrows-Wheeler变换的方法[J].电子与信息学报,37(2):504-508
李井冈,姚运生,李胜乐,等2008基于Oracle的地震前兆数据库表结构对比[J].计算机工程与设计,29(1):243-245
李雷定,马铁华,尤文斌2009常用数据无损压缩算法分析[J].电子设計工程,17(1):49-50
刘高川2008地震前兆数据交换系统设计[D].北京:中国地震局地球物理研究所,1-85
刘红霞,牛富丽2010实时数据库数据压缩算法探讨与改进[J].化工自动化及仪表,37(6):72-75
刘坚,李胜乐,王子影2009基于LZMA的数据库压缩存储应用研究[J].大地测量与地球动力学,29(6):144-147
姚运生,李井冈,李胜乐2006提高地震前兆数据库存取效率的新表结构[J].大地测量与地球动力学,26(3):126-130
张静,王永敏2011数据库应用系统中LOB应用技术研究[J].计算机技术与发展,21(2):166-169
郑翠芳2011几种常用无损数据压缩算法研究[J].计算机技术与发展,21(9):73-76
周克昌,蒋春花,纪寿文,等2010地震前兆数据库系统设计[J].地震,30(2):143-151
周克昌,张崇立,纪寿文,等2009中国地震前兆台网主要问题探讨[J].地震地磁观测与研究,30(1):76-80