一种数据库数据读写方法和装置
技术领域
本发明涉及数据库技术领域,尤指一种数据库数据读写方法和装置。
背景技术
伴随着新项目立项,构建新工程时,需要大量数据初始化数据库,这些数据往往来自多个外围系统数据库,本系统的一个数据表经常需要从多个外围数据库同步数据,项目开始阶段需要花费大量时间开发定时任务从不同数据库的不同数据表中同步数据到本系统。
通常情况下选择一种流行的(ORM)数据库映射框架,比如Hibernate,不用写SQL语句,从外围数据库读取,遍历数据列表,逐条插入到数据库中。这种模式在开发中效率较高,代码编写较快。
但是在实际生产中,碰到几十万、上百万甚至更庞大的数据时,这种方式无比缓慢,一个后台同步数据任务,可能一周都跑不完。虽然很多模块的开发工作都已完成,但是因为初始数据不满足,无法得到正确的结果,反而延误工作。
发明内容
为了解决上述问题,本发明提出了一种数据库数据读写方法和装置,能够提高数据库同步业务的处理能力。
为了达到上述目的,本发明提出了一种数据库数据读写装置,设置在数据服务器上,所述数据库数据读写装置包括:
读取单元,用于从应用服务器中读取原始数据,对所述原始数据进行封装以得到目标数据,并将所述目标数据存储到缓存队列中;
提交单元,用于根据预设的缓存读取条件,将缓存队列中缓存的目标数据存储到数据库中。
优选地,所述读取单元从应用服务器中读取原始数据包括:
从应用服务器中读取条数为第一预定数目的原始数据;
在完成对第一预定数目的原始数据的封装并得到对应的第一目标数据,且第一目标数据全部存储到缓存队列之后,在没有完成全部原始数据的读取时,再次从应用服务器中读取条数为第一预定数目的原始数据。
优选地,所述提交单元根据预设的缓存读取条件,将缓存队列中缓存的目标数据存储到数据库中包括:
根据预定的读取间隔,将缓存队列中的目标数据批量存储到数据库中。
优选地,所述提交单元将所述目标数据批量存储到数据库中包括:
预编译存储指令,每次向数据库提交数据时,捆绑Ni条目标数据到存储指令上,执行存储指令,以将Ni条目标数据存储到数据库中;其中,Ni为本次批量存储需存储数目。
优选地,所述提交单元根据预定的读取间隔,将缓存队列中的目标数据批量存储到数据库中包括:
根据预设的批量保存条数Nx,依次批量保存缓存队列中的目标数据;每次保存的目标数据的最大数目为预设的批量保存条数Nx;
其中,
获取缓存队列中存储的数据的长度N1;
若N1小于或等于0,结束本次存储操作;
若N1大于0且小于或等于Nx,将N1条数据以批量存储的方式存储到数据库中;
若N1大于Nx,分N_subs次将目标数目存储到数据库中,其中,在第1次至第N_subs-1次,将Nx条数据存储到数据库中,在第N_subs次时,将Nx条目标数据存储到数据库中;其中,N_subs等于N1除以Nx的整数商加1。
为了达到上述目的,本发明还提出了一种数据库数据读写方法,所述方法包括:
从应用服务器中读取原始数据,对所述原始数据进行封装以得到目标数据,并将所述目标数据存储到缓存队列中;
根据预设的缓存读取条件,将缓存队列中缓存的目标数据存储到数据库中。
优选地,所述从应用服务器中读取原始数据包括:
从应用服务器中读取条数为第一预定数目的原始数据;
在完成对第一预定数目的原始数据的封装并得到对应的第一目标数据,且第一目标数据全部存储到缓存队列之后,在没有完成全部原始数据的读取时,再次从应用服务器中读取条数为第一预定数目的原始数据。
优选地,所述根据预设的缓存读取条件,将缓存队列中缓存的目标数据存储到数据库中包括:
根据预定的读取间隔,将缓存队列中的目标数据批量存储到数据库中。
优选地,所述将所述目标数据批量存储到数据库中包括:
预编译存储指令,每次向数据库提交数据时,捆绑Ni条目标数据到存储指令上,执行存储指令,以将Ni条目标数据存储到数据库中;其中,Ni为本次批量存储需存储数目。
优选地,所述根据预定的读取间隔,将缓存队列中的目标数据批量存储到数据库中包括:
根据预设的批量保存条数Nx,依次批量保存缓存队列中的目标数据;每次保存的目标数据的最大数目为预设的批量保存条数Nx;
其中,
获取缓存队列中存储的数据的长度N1;
若N1小于或等于0,结束本次存储操作;
若N1大于0且小于或等于Nx,将N1条数据以批量存储的方式存储到数据库中;
若N1大于Nx,分N_subs次将目标数目存储到数据库中,其中,在第1次至第N_subs-1次,将Nx条数据存储到数据库中,在第N_subs次时,将Nx条目标数据存储到数据库中;其中,N_subs等于N1除以Nx的整数商加1。
与现有技术相比,本发明提供的技术方案包括:数据库数据读写装置包括:读取单元,用于从应用服务器中读取原始数据,对所述原始数据进行封装以得到目标数据,并将所述目标数据存储到缓存队列中;提交单元,用于根据预设的缓存读取条件,将缓存队列中缓存的目标数据存储到数据库中。通过本发明的方案,将数据库数据同步过程中的读写任务分离,读取单元从外围数据库读取数据并封装后,没有直接存储到数据库,而是写到高速缓存队列中,缓存队列具有较高的读写速率,从而提高了读任务的效率,提交单元从队列中取出数据,按照给定步长,批量保存,从而提高写任务的效率。读取单元和提交单元在缓存队列不发生阻塞的情况下,各自独立运行,从而提高并发效率。
附图说明
下面对本发明实施例中的附图进行说明,实施例中的附图是用于对本发明的进一步理解,与说明书一起用于解释本发明,并不构成对本发明保护范围的限制。
图1为本发明实施例提出的一种实施数据库数据读写方法的系统架构示意图;
图2为本发明实施例提出的一种数据库数据读写装置的结构示意图;
图3为本发明实施例提供的一种数据库数据读写方法的流程示意图;
图4为本发明实施例提供的一种数据库数据读写方法的流程示意图。
具体实施方式
为了便于本领域技术人员的理解,下面结合附图对本发明作进一步的描述,并不能用来限制本发明的保护范围。需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的各种方式可以相互组合。
应当理解,此处所描述的具体实施例仅用以解释本发明,并不用于限定本发明。
现在将参考附图描述实现本发明各个实施例的移动终端。在后续的描述中,使用用于表示元件的诸如“模块”、“部件”或“单元”的后缀仅为了有利于本发明的说明,其本身并没有特定的意义。因此,"模块"与"部件"可以混合地使用。
本发明实施例中,从两个维度来分解数据库的数据同步任务,将传统的数据同步任务进行读写剥离,通过维持一个高速缓存队列暂时保持数据,第一、从外围的应用数据库读数据,然后将数据写到一个设置的高速缓存队列中;第二、从高速缓存队列取数据,然后批量插入到本地数据库中,保存过程中,设置一个批量步长,比如100,存储数据达到100条之后,再一次commit(保存)到本地数据中,或者设置一个保存时长间隔,例如,10S,每次到达保存时长间隔时一次性commit到本地数据中。
本发明实施例中,在将缓存队列中的数据保存到数据库时,采用JDBC保存。
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
JDBC是Java语言执行SQL访问数据库的标准接口。
Hibernate是一个对象关系映射框架,在JDBC的基础上进行封装,将Java数据模型与数据库表建立映射关系,自动生成SQL,是一个全自动的ORM框架。
从执行效率上考虑,JDBC无疑是最快的,单条数据上二者差异不大,但是在大数据操作数据库情况下,Hibernate单条插入,需要进行对象映射、生成SQL等操作以及自身的机制问题使性能下降的非常快,Hibernate批量操作只是按步长批量提交数据库执行映射的SQL,不是真正意义上的批量操作,JDBC的批量保存采用PreparedStatement接口预编译执行语句,能够最大程度的优化性能。
首先,对实施本发明实施例提供的数据库数据读写方法的系统架构进行说明。如图所示,实施本发明实施例提供的数据库数据读写方法的系统分4个层次,层次架构图如1所示,其中,该系统中包括应用服务器、核心业务模块、缓存队列、数据持久层和操作系统。
其中,应用服务器采用Tomcat服务器,实现模块部署,所述应用服务器可以为多个。
其中,核心业务模块,核心业务模块包括读取单元和提交单元,读取单元用于读取外围的应用数据库,存入缓存队列中,缓存队列中存放的数据为本地数据的表数据模型;提交单元用于将缓存队列的数据存储到本地数据库,其中,从缓存队列中取出数据列表,分批插入数据,其中,可以使用commit命令执行插入。
其中,缓存队列为有界队列,队列满时阻塞,直到有空间才存入;队列空时阻塞,直到有数据才取出,多线程同步情况下能够保持数据的一致性,队列数据放在缓存中,存取效率高。
其中,数据持久层,有本地数据和多个外围数据库组成。
其中,操作系统可选的采用CentOS 7的64版本操作系统。
下面结合附图,对本发明实施例提供的数据库数据读写装置和方法进行说明。
如图2所示,本发明实施例提出一种数据库数据读写装置,设置在服务器上,所述数据库数据读写装置包括:
读取单元10,用于从应用服务器中读取原始数据,对所述原始数据进行封装以得到目标数据,并将所述目标数据存储到缓存队列中;
提交单元20,用于根据预设的缓存读取条件,将缓存队列中缓存的目标数据存储到数据库中。
其中,读取单元10依次将目标数据存储到缓存队列的队尾中,提交单元20从缓存队列的队首中依次取出数据,并插入到数据库中。
首先对读取单元10的工作过程进行说明。
本发明实施例中,所述读取单元10从应用服务器中读取原始数据包括:
从应用服务器中读取条数为第一预定数目的原始数据;
在完成对第一预定数目的原始数据的封装并得到对应的第一目标数据,并且第一目标数据全部存储到缓存队列之后,再次从应用服务器中读取条数为第一预定数目的原始数据。其中,第一目标数据为对一次读取的原始数据封装之后得到的目标数据。
从应用服务器中读取原始数据需要通过网络请求完成,较为费时,因此,通过第一预定数目批量完成原始数据的读取。
例如,本次数据库同步的全部原始数据为10000条,将第一预定数目设置为1000条,每次从应用服务器中读取1000条原始数据,共10次读出全部原始数据。
其中,第一预定数目设置为500~2000,例如,可以设置为1000条,第一预定数目是根据网络流程以及系统缓存的大小所设置的。
其中,在封装好一条目标数据之后,将封装的目标数据插入到缓存队列的队尾。
其中,为了保证数据安全,不产生脏数据,保存封装的目标数据到缓存队列的过程中,会涉及数据一致性问题,例如,在多线程环境下产生的数据同步问题,在多线程环境下,可能通过不同线程重复写入同一条目标数据,为了保证缓存队列中目标数据的唯一性,读取单元10需要在将封装的目标数据存储到缓存队列之前,进行待写入的目标数据的唯一性判断。
读取单元10进行待写入的目标数据的唯一性判断包括:
判断待写入的目标数据在数据库中是否存在,如果在数据库中不存在,则判断待写入的目标数据在缓存队列中是否存在,如果在缓存队列中不存在,则将待写入的目标数据插入到缓存队列。如果待写入的目标数据在数据库中存在,或待写入的目标数据在缓存队列中存在,则删除该待写入的目标数据,判断待写入的目标数据是否存在的依据是每条目标数据中的唯一性Id。
通过一致性判断,在多线程同步情况下能够保持数据的一致性,队列数据放在缓存中,存取效率高。其中,缓存队列为高速缓存队列。
下面对提交单元20的工作过程进行说明。
本发明实施例中,所述提交单元20根据预设的缓存读取条件,将缓存队列中缓存的目标数据存储到数据库中包括:
根据预定的读取间隔,将缓存队列中的目标数据批量存储到数据库中。
其中,读取间隔可以设置为5~20s,例如,可以设置为5s或者10s。
其中,将缓存队列中的目标数据批量存储到数据库中包括:
根据预设的批量保存条数Nx,依次批量保存缓存队列中的目标数据,其中,每次保存的目标数据的最大数目为预设的批量保存条数Nx。
本发明实施例中,所述提交单元20将缓存队列中的目标数据批量存储到数据库中包括:
预编译存储指令,每次向数据库提交数据时,捆绑Ni条目标数据到存储指令上,执行存储指令,以将Ni条目标数据存储到数据库中;其中,Ni为本次批量存储需存储数目。其中存储指令可以是sql语句。
本发明实施例中,所述提交单元20根据预定的读取间隔,将缓存队列中的目标数据存储到数据库中包括:
根据预设的批量保存条数Nx,依次批量保存缓存队列中的目标数据;每次保存的目标数据的最大数目为预设的批量保存条数Nx;
其中,
获取缓存队列中存储的数据的长度N1;
若N1小于或等于0,结束本次存储操作;
若N1大于0且小于或等于Nx,将N1条数据以批量存储的方式存储到数据库中;
若N1大于Nx,分N_subs次将目标数目存储到数据库中,其中,在第1次至第N_subs-1次,将Nx条数据存储到数据库中,在第N_subs次时,将Nx条目标数据存储到数据库中;其中,N_subs等于N1除以Nx的整数商加1。
本发明实施例提供的数据库数据读写装置至少具有如下技术效果:
(1)将数据库数据同步过程中的读写任务分离,读取单元从外围数据库读取数据并封装后,没有直接存储到数据库,而是写到高速缓存队列中,提交单元从队列中取出数据,按照给定步长,批量保存。从而提高并发效率。
(2)使用原生jdbc API,相较于OM框架,减少对象映射以及多次sql执行的开销,执行效率提高显著。
(3相关技术中,通常同步任务包括三个部分,第一、从外围数据库读取,第二、逐条数据组装,第三、在组装数据之后逐条保存。经过分解任务后,把第三步修改为暂时保存到缓存队列中,由于高速缓存的写入速度远远高于数据库,因此读取任务能大大提高效率;批量保存任务直接从缓存队列中读取数据,这个过程效率比较高,只需要每段时间,比如每10秒,从缓存队列取一次数据就能批量保存完队列的所有数据。
基于与上述实施例相同或相似的构思,本发明实施例还提供一种数据库数据读写方法,参见图3,为本发明实施例提供的数据库数据读写方法的流程示意图,如图3所示,所述数据库数据读写方法包括:
步骤100,从应用服务器中读取原始数据,对所述原始数据进行封装以得到目标数据,并将所述目标数据存储到缓存队列中。
如图4所示,步骤100具体包括:
步骤110,从应用服务器中读取条数为第一预定数目的原始数据;
从应用服务器中读取原始数据需要通过网络请求完成,较为费时,因此,通过第一预定数目批量完成原始数据的读取。
例如,本次数据库同步的全部原始数据为10000条,将第一预定数目设置为1000条,每次从应用服务器中读取1000条原始数据,共10次读出全部原始数据。
其中,第一预定数目设置为500~2000,例如,可以设置为1000条,第一预定数目是根据网络流程以及系统缓存的大小所设置的。
步骤120,根据读取的原始数据,基于业务数据模型对原始数据进行封装,获取封装的目标数据;
根据不同的业务数据模型,封装的目标数据的数目与第一预定数目相同或者不同。在对原始数据进行封装时,需要遍历全部读取的原始数据;
步骤130,将封装的目标数据存储到缓存队列。
其中,在封装好一条目标数据之后,将封装的目标数据插入到缓存队列的队尾。
其中,为了保证数据安全,不产生脏数据,保存封装的目标数据到缓存队列的过程中,会涉及数据一致性问题,例如,在多线程环境下产生的数据同步问题,在多线程环境下,可能通过不同线程重复写入同一条目标数据,为了保证缓存队列中目标数据的唯一性,需要在将封装的目标数据存储到缓存队列之前,进行待写入的目标数据的唯一性判断。
进行待写入的目标数据的唯一性判断包括:
判断待写入的目标数据在数据库中是否存在,如果在数据库中不存在,则判断待写入的目标数据在缓存队列中是否存在,如果在缓存队列中不存在,则将待写入的目标数据插入到缓存队列。如果待写入的目标数据在数据库中存在,或待写入的目标数据在缓存队列中存在,则删除该待写入的目标数据,判断待写入的目标数据是否存在的依据是每条目标数据中的唯一性Id。
多线程同步情况下能够保持数据的一致性,队列数据放在缓存中,存取效率高。其中,缓存队列为高速缓存队列。
步骤140,重复执行步骤110~130,直至完成全部原始数据的读取。
在所述从应用服务器中读取条数为第一预定数目的原始数据全部封装完毕并得到对应的目标数据,并且上述目标数据全部存储到缓存队列之后,执行下一次的从应用服务器中读取条数为第一预定数目的原始数据的步骤。
当应用服务器中剩余待读取数据不足第一预定数目时,读取全部应用服务器中剩余待读取数据。
步骤200,根据预设的缓存读取条件,将缓存队列中缓存的目标数据存储到数据库中。
步骤200具体包括:
步骤210,根据预定的读取间隔,将缓存队列中的目标数据存储到数据库中。
其中,读取间隔可以设置为5~20s,例如,可以设置为5s或者10s。
其中,将缓存队列中的目标数据存储到数据库中包括:
根据预设的批量保存条数Nx,依次批量保存缓存队列中的目标数据,其中,每次保存的目标数据的最大数目为预设的批量保存条数Nx。
本发明实施例中,将缓存队列中的目标数据批量存储到数据库中包括:
预编译一条sql语句,遍历过程中捆绑本次批量存储需存储数目的目标数据到sql上,执行上述一条sql语句,以将本次批量存储需存储数目的目标数据存储到数据库中。
例如,批量保存条数Nx设置为100,如果缓存队列中的目标数据共有360条,则分4次保存,第1次至第3次分别保存100条,第4次保存60条。
具体地,示例性地,步骤210包括:
步骤2101,获取缓存队列中存储的数据的长度N1;
步骤2102,若N1小于或等于0,结束本次存储操作;
步骤2103,若N1大于0且小于或等于Nx,将N1条数据以批量存储的方式存储到数据库中;其中,将N1条数据存储到数据库中包括:预编译一条sql语句,遍历过程中将N1条数据捆绑到sql上,通过编译的sql语句将N1条数据批量插入到数据库中
步骤2104,若N1大于Nx,分N_subs次将目标数目存储到数据库中,其中,在第1次至第N_subs-1次,将Nx条数据存储到数据库中,在第N_subs次时,将Nx条目标数据存储到数据库中;其中,N_subs=[N1/Nx]+1,其中,[]表示舍尾法取整。
例如,若N1大于Nx,设置遍历次数N_loops,提交数据库次数设为N_subs,则N_loops=[N1/Nx],其中,[]表示舍尾法取整,N_subs=N_loops+1,遍历前首先预编译一条sql语句,遍历过程中每次捆绑Nx条数据到sql上,然后批量插入到数据库中,知道完成N_loops次遍历,此时已经完成N_loops次提交数据库,还有一次提交数据库是绑定N1%Nx条数据到sql上;其中,N1%Nx为N1除以Nx得到的余数。
步骤220,重复步骤210直至完成全部原始数据的读写操作。
本发明实施例中,步骤100和步骤200可以并行运行。
下面结合一个具体的示例进行说明。
表1应用Jdbc技术写入数据库与之前的Hibernate单条插入的对比
表1中,修改前为现有技术的Hibernate单条插入技术实施的数据库间的数据同步,修改后为本发明实施例提供的数据读写方法进行数据库间的数据同步,其中,本示例中只选取1~10000的每个阶段数据进行测试,从上面测试结果,可以看出,采用本发明实施例提供的数据读写方法分解任务后,效率提升明显,大约提升30%,在实际任务能节约三分之一的时间,加快了项目进度。
其中,实验测试环境如下:
处理器:Intel(R)Pentinum(R)CPU G3250@3.20GHz 3.20GHz
安装内存:4GB
系统类型:64位
系统版本:Windows 7旗舰版
Hibernate批量数据存储包括:从应用服务器中读取数据;遍历每条数据,根据业务需要封装成业务数据模型;将封装好的数据存入到Hibernate的缓存中,当Hibernate缓存提交达到预定数目后,Hibernate将预定数目的数据对象提交到数据库,例如,预定数目为100时,当Hibernate缓存提交达到100后,数据库执行100次这100条数据的插入。
Hibernate缓存是Hibernate框架捆绑的,是为操作数据库服务的,用于操作sql的中间数据,不是直接用于存储业务的中间数据,本发明实施例中,从应用服务器读取的原始数据,以及根据原始数据封装得到的目标数据都属于中间数据,并非操作sql的中间数据,无法利用Hibernate缓存进行缓存,本实施例中,通过数据库数据读写装置创建缓存队列,并利用缓存队列存储目标数据,此外,本发明实施例中,可以根据写任务决定缓存队列中缓存的数据的生命周期,按照特定的缓存读取间隔(或缓存读取频率)来将缓存队列中的数据提交到数据库,能够通过上述间隔或频率的调整做好读任务和写任务之间的平衡,使得数据库数据读写达到性能最优。
此外,Hibernate的一次批量提交虽然也是一次操作数据库,但是提交数据跟Jdbc批量插入有本质上的区别,具体以下两点,第一,Hibernate需要为每条数据映射成sql语句;例如,在存储100条数据时,需要为每一条数据编译一次sql语句,也就是要编译100次sql语句,第二,Hibernate批量插入实际上是执行每条sql语句,不是真正的批量提交;本发明实施例中,采用Jdbc批量提交进行存储,其中,首先预编译一条sql语句在内存中,然后向sql捆绑给定条数目的数据,再一次提交到数据库,因此,通过使用Jdbc批量插入,提高了数据存储的速度。
本发明实施例中,还包括从多个服务器读取原始数据并提交到数据库的场景,以从2个服务器读取原始数据为例,该应用环境下,包括:
分别从两个服务器中读取原始数据;根据两个服务器中的数据关系确定各个服务器中读取原始数据的条数;
根据两个服务器中读取原始数据封装得到目标数据;
将封装得到目标数据插入到缓存队列;
根据预设的缓存读取条件,将缓存队列中缓存的目标数据存储到数据库中。该应用场景中,虽然是从2个服务器读取原始数据,但是同样只需要建立一个缓存队列,用于缓存待提交到数据库的封装好的目标数据。
需要说明的是,在本文中,术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、物品或者装置不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、物品或者装置所固有的要素。在没有更多限制的情况下,由语句“包括一个......”限定的要素,并不排除在包括该要素的过程、方法、物品或者装置中还存在另外的相同要素。
上述本发明实施例序号仅仅为了描述,不代表实施例的优劣。
通过以上的实施方式的描述,本领域的技术人员可以清楚地了解到上述实施例方法可借助软件加必需的通用硬件平台的方式来实现,当然也可以通过硬件,但很多情况下前者是更佳的实施方式。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质(如ROM/RAM、磁碟、光盘)中,包括若干指令用以使得一台终端设备(可以是手机,计算机,服务器,空调器,或者网络设备等)执行本发明各个实施例所述的方法。
以上仅为本发明的优选实施例,并非因此限制本发明的专利范围,凡是利用本发明说明书及附图内容所作的等效结构或等效流程变换,或直接或间接运用在其他相关的技术领域,均同理包括在本发明的专利保护范围内。