JDBC的批量更新测试

上回书说道MySQL的auto-reconnect的问题,可以通过重新建立Connection的方法解决之,于是我就更新了一下该数据库封装 类。这里介绍一下背景:为了使用方便,一些小型项目中,我倾向于直接使用JDBC,这样执行效率和开发效率相对而言都比较高,而实际使用中,所有的数据库 操作,都被封装在一个DatabaseFactory类中(有时间我会考虑一下,整理一下Open Source It)。

在修改这个类的过程中,顺便研究了下数据批量更新的效率问题,分析结果如下。由于对于不同的数据库,效果也不尽相同,这里以MySQL和Oracle为例,并分开描述:

MySQL:

MySQL本身并不支持批量更新,只是驱动程序提供了这个特性,只有高版本才支持该特性,并且连接URL上必须加上

1
rewriteBatchedStatements=true

这样的参数,这样驱动程序会自动将多条SQL语句拼接成一条,从而提高了执行效率。

1
2
3
4
5
6
7
...
for (int i = 0; i < sqlList.size(); i++) {
stmt.addBatch(sqlList.get(i));
}
 
stmt.executeBatch();
connection.commit();

效率提升是必然的,原因很简单:非批量更新方式,autoCommit=true,每一条SQL语句都会自动提交,都会产生网络数据包、磁盘IO。 而批量更新方式,只会产生少量的数据包,因为很多条SQL语句被打成一个数据包,一次性的通过网络传输到服务器,相应的,服务器的IO操作也少了很多,当 然效率自然会提高。

就是因为这个和网路相关,所以网络环境不同,产生的提升效果也不相同,经测试,在比较快速的网络环境下,比如局域网,我的试验结果是:10万条SQL语句,在非批量情况下,使用了约36秒,而批量操作只使用了约9秒,效率提高了3倍。

如果在比较差的网络环境下,提升的效果会更明显,我使用VPN从家里连接到公司的内网,更新1万条数据,非批量 方式,大概需要270秒左右,而批量方式大约9秒,提升了近30倍。效率提升的倍数和很多因素相关,比如刚才提到的网络环境,每次提交多少条SQL语句也 很关键,并且MySQL表的类型也会影响这个:MyISAM类型的表的提升效率就远远的高于InnoDB类型的表。

注:上述的所有的所有测试都没有使用Prepared Statement,只是使用普通的Statement和executeBatch(),如果使用Prepared Statement,几乎没有任何效率提升,后来发现是因为我用的mysql-connector-java的版本过低(5.1.8),替换为 5.1.17后,VPN状态,效率提升50倍左右。

Oracle:

和MySQL相反,Oracle使用批量更新,如果不使用Prepared Statement,效果可能会更差,使用了Prepared Statement,我用VPN连接到公司的内网,效率提高了75倍左右。可能是因为我用的Oracle JDBC驱动对非Prepared Statement的支持不够好吧。

MSSQL:

待测试,稍后更新…

小结

数据库更新的效率提升,由很多原因决定:网络环境,服务器内存、服务器I/O、驱动版本、代码编写方式、数据库的版本、表的类型等。我们必须综合考量所有因素,才能达到理想的效果。推荐你在你实际的环境中做相应的测试,找出最优的方法,别人的优化方法,不一定完全适用于你,比如这里提到的提升倍数,每个人的试验结果肯定不一样。

原文地址:https://www.cnblogs.com/shihao/p/2555489.html