(一)首先想到的问题是,mysql方面采用何种方式插入
显然不能500万次连接插入
查阅了文章,https://blog.csdn.net/frinder/article/details/38830723
关于批量插入数据之我见(100万级别的数据,mysql)
总结:方法一和方法二很类同,唯一不同的是方法一采用的是“insert into tb (...) values(...),(...)...;”的方式执行插入操作,
方法二则是“insert into tb (...) values (...);insert into tb (...) values (...);...”的方式,要不是测试,我也不知道两者差别是如此之大!
当然,这个只是目前的测试,具体执行时间和步长也有很大关系!如过把步长改为100,可能方法就要几分钟了吧,这个可以自己测试哈。。。
方法三网上很推崇,不过,效率大家也都看到了,1万条记录,耗时6分钟,可见其效率并不理想!而且方法三需要配置spring applicationContext环境才能应用!
显然,第三种方法,以及这个帖子https://blog.csdn.net/silyvin/article/details/79382892使用的spring jdbctamplate batchupdate是对其中的第2种的封装
(二)其次想到的是,如何确保唯一,这里没使用unique索引,而是使用
INSERT ignore INTO test_random (`value`) VALUES
https://www.cnblogs.com/duanxiaojun/p/6855680.html?utm_source=itdadao&utm_medium=referral
避免unique索引在插入数据时的性能损失
18-04-25 22:42:05,985INFO TestController:387 - TestUnique:4838824
2018-04-25 22:42:06,555INFO TestController:387 - TestUnique:4848317
2018-04-25 22:42:07,121INFO TestController:387 - TestUnique:4857823
2018-04-25 22:42:07,684INFO TestController:387 - TestUnique:4867327
2018-04-25 22:42:08,254INFO TestController:387 - TestUnique:4876819
2018-04-25 22:42:08,821INFO TestController:387 - TestUnique:4886321
2018-04-25 22:42:09,377INFO TestController:387 - TestUnique:4895843
2018-04-25 22:42:10,165INFO TestController:387 - TestUnique:4905344
2018-04-25 22:42:10,737INFO TestController:387 - TestUnique:4914880
2018-04-25 22:42:11,318INFO TestController:387 - TestUnique:4924354
2018-04-25 22:42:11,918INFO TestController:387 - TestUnique:4933854
2018-04-25 22:42:12,484INFO TestController:387 - TestUnique:4943352
2018-04-25 22:42:13,087INFO TestController:387 - TestUnique:4952882
2018-04-25 22:42:13,659INFO TestController:387 - TestUnique:4962400
2018-04-25 22:42:14,224INFO TestController:387 - TestUnique:4971891
2018-04-25 22:42:14,789INFO TestController:387 - TestUnique:4981392
2018-04-25 22:42:15,561INFO TestController:387 - TestUnique:4990908
2018-04-25 22:42:16,117INFO TestController:387 - TestUnique:5000386
2018-04-25 22:42:16,129INFO TestController:407 - cast : 301 s
总耗时301s
public static String generateShortUuid() {
StringBuilder str=new StringBuilder();//定义变长字符串
Random random=new Random();
//随机生成数字,并添加到字符串
for(int i=0;i<8;i++){
str.append(random.nextInt(10));
}
return str.toString();
}
@RequestMapping(value = "testUnique", method = RequestMethod.POST)
@ResponseBody
@ApiImplicitParams({})
@ApiOperation(value="testUnique")
public Object testUnique() {
String driver = "com.mysql.jdbc.Driver";
String URL = "jdbc:mysql://bb:3306/test";
Connection conn = null;
try
{
Class.forName(driver);
}
catch(java.lang.ClassNotFoundException e)
{
// System.out.println("Connect Successfull.");
System.out.println("Cant't load Driver");
}
try {
conn = DriverManager.getConnection(URL,"bb","nnn");
} catch (SQLException e) {
e.printStackTrace();
}
Long begin = new Date().getTime();
// sql前缀
String prefix = "INSERT ignore INTO test_random (`value`) VALUES ";
int count = 0;
while (count <= 5000010) {
try {
// 保存sql后缀j
StringBuffer suffix = new StringBuffer();
// 设置事务为非自动提交
conn.setAutoCommit(false);
// Statement st = conn.createStatement();
// 比起st,pst会更好些
PreparedStatement pst = conn.prepareStatement("");
// 外层循环,总提交事务次数
for (int i = 1; i <= 100; i++) {
// 第次提交步长
for (int j = 1; j <= 100; j++) {
String id = generateShortUuid();
// 构建sql后缀
suffix.append("('");
suffix.append(id);
suffix.append("'),");
}
// 构建完整sql
String sql = prefix + suffix.substring(0, suffix.length() - 1);
// 添加执行sql
pst.addBatch(sql);
// 执行操作
pst.executeBatch();
// 提交事务
conn.commit();
// 清空上一次添加的数据
suffix = new StringBuffer();
}
// 头等连接
pst.close();
String sqlcount = "select count(1) from test_random";
count = jdbcTemplate.queryForObject(sqlcount, Integer.class);
logger.info("TestUnique:"+count);
} catch (SQLException e) {
e.printStackTrace();
logger.error(e);
break;
}
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
// 结束时间
Long end = new Date().getTime();
// 耗时
logger.info("cast : " + (end - begin) / 1000 + " s");
return (end - begin) / 1000;
}