Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案
转自http://www.cnblogs.com/fnz0/p/5713102.html
不知道自己什么时候才有这种钻研精神- -。
1 背景
系统中需要批量生成单据数据到数据库表,所以采用批量插入数据库的方式。由于系统中ORM操作集成使用的是Mybatis来完成的。
在Mybatis中操作一般使用批量插入的方式如下:
<insert id="insertBatch" parameterType="java.util.List" >
insert into userinfo (uid, uname, uphone, uaddress)
values
<foreach collection="list" item="item"index="index" separator=",">
(#{item.uid,jdbcType=INTEGER},
#{item.uname,jdbcType=VARCHAR},
#{item.uphone,jdbcType=VARCHAR},
#{item.uaddress,jdbcType=VARCHAR}
)
</foreach>
</insert>
在实际生产中发现,这样调用的效率并不高,于是我们迫切地需要寻找一种处理批量插入性能较高的方式——回归原生数据库JDBC操作。我们要分析Mybatis和JDBC的插入性能,来决策适合我们生产系统的批量插入方式。
参考资料中有一篇文章是对Spring Mybatis和Spring JDBC插入效率的测试,由于测试的数据量不多不予置评。
2 Mybatis
2.1 Mybatis测试样本1K
测试10组数据:
时间(ms) |
923 |
412 |
426 |
408 |
405 |
353 |
365 |
344 |
316 |
493 |
2.2 Mybatis测试样本2K
测试10组数据:
时间(ms) |
11031 |
3340 |
3571 |
2327 |
7273 |
1353 |
2676 |
1249 |
1245 |
1155 |
2.3 Mybatis测试样本4K
测试10组数据:
时间(ms) |
6070 |
5565 |
5731 |
5400 |
5830 |
5543 |
5469 |
5697 |
5528 |
5399 |
2.4 Mybatis测试样本6K
测试10组数据:
时间(ms) |
13383 |
12672 |
13030 |
13484 |
13841 |
12952 |
13331 |
13275 |
13000 |
13236 |
2.5 Mybatis测试样本8K
测试10组数据:
时间(ms) |
25312 |
24702 |
27065 |
25921 |
25156 |
24686 |
25314 |
33947 |
25304 |
25853 |
2.6 Mybatis测试样本10K
测试10组数据:
时间(ms) |
42148 |
39209 |
38548 |
40109 |
37820 |
37728 |
38178 |
38481 |
38157 |
39032 |
2.7 Mybatis测试样本15K
测试10组数据:
时间(ms) |
98250 |
88585 |
87438 |
89547 |
88427 |
89522 |
83261 |
80842 |
87163 |
84804 |
2.8 Mybatis测试样本20K
测试10组数据:
时间(ms) |
145481 |
146618 |
147098 |
145578 |
144947 |
145614 |
142014 |
142315 |
141984 |
143625 |
2.9 性能测试样本平均值
2.9.1 测试样本SQL
2.9.1.1 毫秒级SQL【time(ms)】
-- DELETE FROMprocess_spend_time_result WHEREpmethod='mybatis';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=1000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=2000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=4000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=6000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=8000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=15000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=20000 ANDp.pmethod='mybatis';
2.9.1.2 秒级SQL【time(s)】
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=1000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=2000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=4000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=6000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=8000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=15000 ANDp.pmethod='mybatis';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=20000 ANDp.pmethod='mybatis';
2.9.2 测试数据汇总
数据4舍5入保留3位小数
测试样例 |
AVG(s) |
1K |
0.445 |
2K |
3.522 |
4K |
5.623 |
6K |
13.221 |
8K |
26.326 |
10K |
38.941 |
15K |
87.784 |
20K |
144.527 |
2.10 Mybatis批量插入问题
2.10.1 问题一:处理性能低下
处理10000条耗时:34292ms
2.10.2 问题二:批量处理数据量大小受限
Windows下需要修改MySQL的my.ini文件加入如下配置内容:
max_allowed_packet=500M
Linux下是在/my.cnf修改添加如上内容。
也可以直接这样设置:
SET GLOBAL max_allowed_packet=1073741824;
但MySQL重启后就不起作用了。
2.10.3 问题三:线程处理锁表
在通过多线程并发处理的时,很容易导致数据库表锁表,使得后续的操作无法进行。
2.10.4 问题四:导致对象回收GC问题
对象超出GC对象回收阀值,导致程序中断。
3 JDBC
3.1 JDBC测试数据1W
测试10组数据:
普通插入(ms) |
普通+事务(ms) |
普通批量(ms) |
批量+事务(MS) |
28489 |
801 |
31287 |
3494 |
30536 |
3042 |
35547 |
1899 |
25571 |
2041 |
31022 |
3501 |
27954 |
2733 |
28927 |
2547 |
29620 |
1261 |
34408 |
1449 |
27125 |
819 |
29318 |
923 |
28993 |
1079 |
31099 |
939 |
27594 |
2547 |
33504 |
3410 |
27967 |
781 |
31646 |
3587 |
33145 |
1293 |
37030 |
1912 |
3.2 JDBC测试数据5W
测试10组数据:
普通插入(ms) |
普通+事务(ms) |
普通批量(ms) |
批量+事务(MS) |
131427 |
11568 |
168623 |
6926 |
132271 |
19313 |
231526 |
9915 |
192176 |
5238 |
227724 |
10978 |
185640 |
18955 |
227497 |
41959 |
211777 |
11238 |
184970 |
9461 |
208446 |
5019 |
263636 |
23394 |
253351 |
14265 |
227391 |
24870 |
225268 |
17009 |
229871 |
5583 |
163739 |
9719 |
230719 |
16657 |
215033 |
15802 |
238018 |
5330 |
3.3 JDBC测试数据10W
测试10组数据:
普通插入(ms) |
普通+事务(ms) |
普通批量(ms) |
批量+事务(MS) |
308773 |
21389 |
360510 |
16432 |
352773 |
23487 |
372343 |
25545 |
378805 |
24034 |
368416 |
12507 |
384189 |
30119 |
392974 |
23742 |
369975 |
30651 |
378634 |
26180 |
368659 |
11902 |
416932 |
21321 |
388453 |
12644 |
411571 |
18138 |
391155 |
11287 |
396363 |
11678 |
368055 |
30987 |
399078 |
12212 |
363375 |
22576 |
361478 |
18544 |
3.4 JDBC测试数据25W
测试10组数据:
普通插入(ms) |
普通+事务(ms) |
普通批量(ms) |
批量+事务(MS) |
942067 |
51343 |
990800 |
70103 |
1070688 |
28737 |
1051132 |
35536 |
1002076 |
38065 |
1222409 |
89644 |
1073114 |
57050 |
1312620 |
82354 |
960697 |
51733 |
1338932 |
33428 |
1025890 |
37666 |
1273338 |
76934 |
1017361 |
50916 |
1115627 |
92790 |
1077821 |
78650 |
1175512 |
52427 |
1038000 |
23290 |
1247797 |
91801 |
1200532 |
75494 |
1262051 |
72087 |
3.5 JDBC测试数据50W
测试10组数据:
普通插入(ms) |
普通+事务(ms) |
普通批量(ms) |
批量+事务(MS) |
1914920 |
166575 |
2059826 |
146472 |
2111596 |
62807 |
1897888 |
125075 |
2174029 |
147265 |
1891542 |
166921 |
1948838 |
61284 |
2129791 |
93167 |
1909861 |
167575 |
1856811 |
56286 |
1990816 |
141381 |
1980060 |
148012 |
1896793 |
48087 |
2065937 |
56832 |
2130856 |
174388 |
2019914 |
113289 |
2073636 |
117462 |
2045715 |
102792 |
1966828 |
141319 |
1857867 |
116854 |
3.6 JDBC测试样本均值
3.6.1 测试样本SQL
3.6.1.1 毫秒级SQL【time(ms)】
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 andp.pmethod='batchInsert';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 andp.pmethod='batchInsertWithTransaction2';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=50000 andp.pmethod='batchInsert';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=50000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=50000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=50000 andp.pmethod='batchInsertWithTransaction2';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=100000 andp.pmethod='batchInsert';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=100000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=100000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=100000 andp.pmethod='batchInsertWithTransaction2';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=250000 andp.pmethod='batchInsert';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=250000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=250000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=250000 andp.pmethod='batchInsertWithTransaction2';
SELECTAVG(p.ptime) FROM process_spend_time_resultp WHEREp.plimit=500000andp.pmethod='batchInsert';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=500000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=500000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=500000 andp.pmethod='batchInsertWithTransaction2';
3.6.1.2 秒级SQL【time(s)】
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 andp.pmethod='batchInsert';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 andp.pmethod='batchInsertWithTransaction2';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=50000 andp.pmethod='batchInsert';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=50000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=50000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime)/1000 FROM process_spend_time_resultp WHEREp.plimit=50000andp.pmethod='batchInsertWithTransaction2';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=100000 andp.pmethod='batchInsert';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=100000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=100000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=100000 andp.pmethod='batchInsertWithTransaction2';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=250000 andp.pmethod='batchInsert';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=250000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=250000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=250000 andp.pmethod='batchInsertWithTransaction2';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=500000 andp.pmethod='batchInsert';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=500000 andp.pmethod='batchInsert2';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=500000 andp.pmethod='batchInsertWithTransaction';
SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=500000 andp.pmethod='batchInsertWithTransaction2';
3.6.2 测试数据汇总
数据4舍5入保留2位小数
测试样例 |
1W(s) |
5W(s) |
10W(s) |
25W(s) |
50W(s) |
普通插入 |
28.70 |
191.91 |
367.42 |
1040.82 |
2011.82 |
普通+事务 |
1.64 |
12.81 |
21.91 |
49.29 |
122.81 |
批量插入 |
32.38 |
223.00 |
385.83 |
1199.02 |
1980.54 |
批量+事务 |
2.37 |
15.51 |
18.63 |
69.71 |
112.57 |
3.7 JDBC测试规律总结
3.7.1 规律一:批量插入尽量使用事务控制
数据4舍5入保留2位小数
测试样例 |
1W(s) |
5W(s) |
10W(s) |
25W(s) |
50W(s) |
普通插入 |
28.70 |
191.91 |
367.42 |
1040.82 |
2011.82 |
普通+事务 |
1.64 |
12.81 |
21.91 |
49.29 |
122.81 |
批量插入 |
32.38 |
223.00 |
385.83 |
1199.02 |
1980.54 |
批量+事务 |
2.37 |
15.51 |
18.63 |
69.71 |
112.57 |
3.7.2 规律二:事务批量处理的数据量不要太大
数据4舍5入保留2位小数
测试样例 |
1W(s) |
5W(s) |
10W(s) |
25W(s) |
50W(s) |
普通插入 |
28.70 |
191.91 |
367.42 |
1040.82 |
2011.82 |
普通+事务 |
1.64 |
12.81 |
21.91 |
49.29 |
122.81 |
批量插入 |
32.38 |
223.00 |
385.83 |
1199.02 |
1980.54 |
批量+事务 |
2.37 |
15.51 |
18.63 |
69.71 |
112.57 |
3.7.3 规律三:适当地设置MySQL参数可以提高数据库性能
数据4舍5入保留2位小数
测试样例 |
1W(s) |
5W(s) |
10W(s) |
25W(s) |
50W(s) |
普通插入 |
28.70 |
191.91 |
367.42 |
1040.82 |
2011.82 |
普通+事务 |
1.64 |
12.81 |
21.91 |
49.29 |
122.81 |
批量插入 |
32.38 |
223.00 |
385.83 |
1199.02 |
1980.54 |
批量+事务 |
2.37 |
15.51 |
18.63 |
69.71 |
112.57 |
3.7.4 规律四:处理数据量和时间不是成倍增长
数据4舍5入保留2位小数
测试样例 |
1W(s) |
5W(s) |
10W(s) |
25W(s) |
50W(s) |
普通插入 |
28.70 |
191.91 |
367.42 |
1040.82 |
2011.82 |
普通+事务 |
1.64 |
12.81 |
21.91 |
49.29 |
122.81 |
批量插入 |
32.38 |
223.00 |
385.83 |
1199.02 |
1980.54 |
批量+事务 |
2.37 |
15.51 |
18.63 |
69.71 |
112.57 |
3.7.5 规律五:数据库性能随数据量的不断加大而降低
数据4舍5入保留2位小数
测试样例 |
1W(s) |
5W(s) |
10W(s) |
25W(s) |
50W(s) |
普通插入 |
28.70 |
191.91 |
367.42 |
1040.82 |
2011.82 |
普通+事务 |
1.64 |
12.81 |
21.91 |
49.29 |
122.81 |
批量插入 |
32.38 |
223.00 |
385.83 |
1199.02 |
1980.54 |
批量+事务 |
2.37 |
15.51 |
18.63 |
69.71 |
112.57 |
4 结论
经过以上测试得出结论:Mybatis的批量适合处理少了数据的批量处理,而JDBC适合大数据量的批量处理。据此,采用JDBC批量+事务处理大数据量的表插入操作是最合适的。
5 方案
因为要考虑JVM的GC所以数据应该限制一下,但鉴于Mybatis大数据量的批量插入效率不高,所以根据数据大小分段治理。
5.1 小于1W使用:Mybatis批量插入方案
对JVM进行调优,但主要的性能瓶颈在批量插入操作。鉴于mybatis在项目开发方面的优势,数据量很小的情况下还是建议使用Mybatis。
5.2 大于1W小于10W使用:JDBC批量+事务处理
对JVM进行调优(设置Stack和GC等)。一般操作30秒以内是可以容忍的性能耗时。
5.3 10W以上数据使用:数据分批+JDBC批量+事务处理
对JVM进行调优(设置Stack和GC等),通过数据分批处理。对于分批处理需要借鉴前面的测试数据来定义分批量的大小,主要是对操作时间调优。
如果是100W、1000W级别的数据量,分批处理可以很大程度地提升插入效率,具体的分批需要通过实践去分配,数据量太大这里就不做实验了。
6 参考资料
JDBC实现往MySQL数据库插入百万数据:http://www.cnblogs.com/fnz0/p/5713102.html
MySQL Max_allowed_packet: http://stackoverflow.com/questions/8062496/how-to-change-max-allowed-packet-size
Spring Mybatis和Spring JDBC的插入效率比较:http://toplchx.iteye.com/blog/1988254
注:另外一种比较高效的导入方式是生成一个文本文件使用MySQL的JDBC LOAD DATA LOCAL INFILE;参考示例:
MySQL使用JDBC LOAD DATA LOCAL INFILE导入注意事项
MySQL使用LOAD DATA LOCAL INFILE数据3-5秒导入40W数据
Java不写文件,LOAD DATA LOCAL INFILE大批量导入数据到MySQL的实现
7.实战演练
注意:事务处理的数据量不能太多。
7.1 JDBC工具类
package com.wlyd.fmcgwms.util.jdbc;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
*JDBC连接工具类
*
*@package com.wlyd.fmcgwms.util.jdbc.JdbcConnection
*@date 2017年4月17日 下午3:32:15
*@author pengjunlin
*@comment
*@update
*/
public class JdbcConnection {
privatestatic Connection conn = null;
private static Properties props = null;
static {
props = new Properties();
try {
props.load(JdbcConnection.class.getResourceAsStream("/jdbc.properties"));
} catch (IOException e1) {
e1.printStackTrace();
}
try {
Class.forName(props.getProperty("jdbc.driverClass"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConn(){
try {
conn = DriverManager.getConnection(props.getProperty("jdbc.jdbcUrl"),props.getProperty("jdbc.user"),props.getProperty("jdbc.password"));
conn.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public void closeConn(){
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
7.2 批量事务插入
7.2.1 接口
/**
* jdbc批量插入
*
* @MethodName: jdbcBatchInsert
* @Description:
* @param user
* @param items
* @return
* @throws Exception
* @throws
*/
int jdbcBatchInsert(EsUser user,List<WmElectronicSheetItem> items) throws Exception;
/**
* jdbc批量插入
*
* @MethodName: jdbcPerBatchInsert
* @Description:
* @param user
* @param items
* @return
* @throws Exception
* @throws
*/
intjdbcPerBatchInsert(EsUser user, List<WmElectronicSheetItem> items) throws Exception;
7.2.2 实现
@Override
publicint jdbcBatchInsert(EsUser user, List<WmElectronicSheetItem> items) throws Exception {
intflag = 0;
intperCount = 100, index = 0;
inttimes = items.size() / perCount;
longstime=System.currentTimeMillis();
try {
do {
// 休眠50ms
Thread.sleep(50);
List<WmElectronicSheetItem>listTemp= null;
if (items.size() >= perCount) {
listTemp = items.subList(0, perCount);// listTemp是分段处理逻辑的参数
}else{
listTemp = items.subList(0, items.size());// listTemp是分段处理逻辑的参数
}
// 遍历当前的值是否正确
Stringresult= "";
for (inti = 0; i < listTemp.size(); i++) {
result += listTemp.get(i) + ",";
}
Log.getLogger(getClass()).info("第" + (index+1)+ "轮:>>" + result);
// 事务单元执行个数==尽量在事务里面处理少一点(事务尽量小一点)
jdbcPerBatchInsert(user, listTemp);
items.removeAll(listTemp);
Log.getLogger(getClass()).info("当前剩余集合长度:>>" + items.size());
index++;
}while(index<= times);
// 计算时间
longetime=System.currentTimeMillis();
Log.getLogger(getClass()).info(">>封装面单号批量事务插入总共耗时-----------------------:"+(etime-stime)+"ms!");
}catch(Exception e) {
e.printStackTrace();
flag=2;
Log.getLogger(getClass()).error("JDBC批量执行插入异常:>>" + items.size());
thrownew RuntimeException();
}
returnflag;
}
@Override
publicintjdbcPerBatchInsert(EsUser user, List<WmElectronicSheetItem> items)
throws Exception {
intflag=0;
Connectionconn=JdbcConnection.getConn();
PreparedStatementpstm= null;
try {
Stringsql= "insert intowm_electronic_sheet_item_? ("
+"WESI_WESB_ID,WESI_CARRIER_CODE,WESI_START_CHARACTER,WESI_SEQUENCE,"
+"WESI_WAREHOUSE_ID, WESI_CODE,WESI_STATE, "
+"CREATOR, CREATE_TIME, MODIFIER,MODIFY_TIME) values"
+"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
conn.setAutoCommit(false);
Log.getLogger(getClass()).info(">>>>>>验证JDBC连接:"+(conn!=null));
for (inti = 0, j = items.size(); i < j; i++) {
WmElectronicSheetItemitem= items.get(i);
pstm = conn.prepareStatement(sql);
pstm.setInt(1, Integer.valueOf(user.getEsCorCode())); // tableName
pstm.setInt(2, item.getWesiWesbId());// WESI_WESB_ID
pstm.setString(3, item.getWesiCarrierCode());// WESI_CARRIER_CODE
pstm.setString(4, item.getWesiStartCharacter());// WESI_START_CHARACTER
pstm.setString(5, item.getWesiSequence());// WESI_SEQUENCE
pstm.setInt(6, item.getWesiWarehouseId());// WESI_WAREHOUSE_ID
pstm.setString(7, item.getWesiCode());// WESI_CODE
pstm.setInt(8, item.getWesiState());// WESI_STATE
pstm.setInt(9, user.getEsId());// CREATOR
pstm.setTimestamp(10,new java.sql.Timestamp(new Date().getTime()));// CREATE_TIME
pstm.setInt(11, -1);// MODIFIER
pstm.setTimestamp(12, null);// MODIFY_TIME
pstm.executeUpdate();
}
conn.commit();// 手动提交事务
}catch(Exception e) {
e.printStackTrace();
flag=2;
Log.getLogger(getClass()).error("JDBC批量分配事务单元执行插入异常:>>" + items.size());
thrownew RuntimeException();
}finally{
if (pstm != null) {
try {
pstm.close();
}catch(SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
conn.close();
}
}
returnflag;
}
7.3测试一组数据
测试50000条数据耗时统计:
数据样本事务大小 (每个事务处理的数量) |
耗时(ms) |
100 |
100258 |
500 |
75041 |
1000 |
68850 |
3000 |
78354 |
通过这种方式提交比较安全不会出现线程锁表问题,事务处理尽量少,根据每次事务提交执行的量可以实现时间上的优化。
Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案的更多相关文章
- python批量插入mysql数据库(性能相关)以及反引号的使用
参考link: https://blog.csdn.net/qq_35958094/article/details/78462800(插入相关) https://www.cnblogs.com/hya ...
- 关于 MyBatis MyBatis-Spring Jdbc 批量插入的各种比较分析
因为目前SME项目中编写了一套蜘蛛爬虫程序,所以导致插入数据库的数据量剧增.就项目中使用到的3种DB插入方式进行了一个Demo分析: 具体代码如下: 1: MyBatis 开启Batch方式,最普通的 ...
- Mybatis插入MySQL数据库中文乱码
Mybatis插入MySQL数据库中文乱码 在dataSource.properties配置文件中设置useUnicode=true&characterEncoding=utf-8编码即可. ...
- 三种JDBC批量插入编程方法的比较
JDBC批量插入主要用于数据导入和日志记录因为日志一般都是先写在文件下的等. 我用Mysql 5.1.5的JDBC driver 分别对三种比较常用的方法做了测试 方法一,使用PreparedStat ...
- jdbc批量插入
分享牛,分享牛原创.有这样一个需求,文本文件中的数据批量的插入mysql,怎么用jdbc方式批量插入呢? jdbc默认提供了批量插入的方法,可能用一次就忘记了,这里做笔记记录一下jdbc批量插入吧. ...
- JDBC批量插入数据优化,使用addBatch和executeBatch
JDBC批量插入数据优化,使用addBatch和executeBatch SQL的批量插入的问题,如果来个for循环,执行上万次,肯定会很慢,那么,如何去优化呢? 解决方案:用 preparedSta ...
- MyBatis 使用 foreach 批量插入
MyBatis 使用 foreach 批量插入 参考博文 老司机学习MyBatis之动态SQL使用foreach在MySQL中批量插入 使用MyBatis一次性插入多条数据时候可以使用 <for ...
- SpringMVC文件上传 Excle文件 Poi解析 验证 去重 并批量导入 MYSQL数据库
SpringMVC文件上传 Excle文件 Poi解析并批量导入 MYSQL数据库 /** * 业务需求说明: * 1 批量导入成员 并且 自主创建账号 * 2 校验数据格式 且 重复导入提示 已被 ...
- Weka里如何将arff文件或csv文件批量导入MySQL数据库(六)
这里不多说,直接上干货! 前提博客是 Weka中数据挖掘与机器学习系列之数据格式ARFF和CSV文件格式之间的转换(四) 1.将arff文件批量导入MySQL数据库 我在这里,arff文件以Weka安 ...
随机推荐
- Unity 阴影的制作方式
Unity阴影制作的三种方式. 方式一:Light中Shadow Type的类型 包括Hard Shadows.Soft Shadows.No Shadows: Mesh Renderer中的属性 ...
- Prometheus-配置解析
1.Prometheus整体架构图 2.配置文件 # 全局配置 global: scrape_interval: 15s # 多久 收集 一次数据 evaluation_interval: 30s # ...
- A Graph Partitioning Game Theoretical Approach for the VNF Service Chaining Problem
文章名称:A Graph Partitioning Game Theoretical Approach for the VNF Service Chaining Problem 发表时间:2017 期 ...
- 1.5分布式通讯框架-RMI
分布式通信框架-RMI讲解 什么是RPC Remote procedure call protocal RPC协议其实是一个规范.常用PRC框架:Dubbo.Thrif.RMI.Webservice. ...
- 大数据基础-2-Hadoop-1环境搭建测试
Hadoop环境搭建测试 1 安装软件 1.1 规划目录 /opt [root@host2 ~]# cd /opt [root@host2 opt]# mkdir java [root@host2 o ...
- 6.linux安装tomcat
1.下载安装包 https://tomcat.apache.org/download-80.cgi 2.用 WinSCP 将本地的安装包 上传到 linux 服务器中 3.解压安装包( ...
- C# - Visual Studio简明操作
Visual Studio简明操作 安装Northwind示例数据库 运行安装程序,结束安装后,再CMD中输入以下命令 cd C:\SQL Server Sample Databases(回车) s ...
- XL4001 典型应用电路
典型的应用电路如下: 中文数据手册:https://wenku.baidu.com/view/98ad2ed86f1aff00bed51ec7.html 在做毕设的时候用到的一款350ma的DC/DC ...
- Easyui datalist 使用记录
仅简单记录下,资料相对比较少 官方给了一个很简单的例子,没啥用处,文档:http://www.jeasyui.com/documentation/datalist.php 学习要点: 1.追加行 $( ...
- git提交忽略某些文件或文件夹
记得第一次用 github 提交代码,node_modules 目录死活传不上去,哈哈哈,后来才知道在 .gitignore 文件里设置了忽略 node_modules 目录上传.是的, .gitig ...