Mysql数据库快速插入亿级数据
接手一个项目,该项目运行了两三年了。接手的时候,只有一个部署文档和全部代码,再没有其他文档了,也没有其他任何人了解这个项目。好吧,试着深入了解吧。代码在测试环境跑来了,整个项目算是看得七七八八了。去线网看看,我靠,mysql数据库数据已经好几十个G了。定位到其中一张表t_send_message_send,发送短信的记录表,已经一亿多条数据了,占用空间四十多个G,索引6个G多。分区吧,按时间分区,分区能加快查询速度,以后也可以分区清理数据。线网数据不敢动啊,也不会分区。保险起见,在测试环境操作熟了再说。好吧,就先在自己的破机器上造一亿条数据。
造数据方法也很多,常见的有写存储过程、写代码插入、load data导入。存储过程不熟,load data不会,我写代码吧,这个相对简单。代码参考了这位博主。https://blog.youkuaiyun.com/vicky_pyh/article/details/92088613。实践了他说的代码插入最快的一种方式,jdbc批量插入。代码如下:
package com.maanjun;
import java.sql.*;
import java.util.*;
public class InsertBigdata {
//该代码为开启事务
private long begin = 1;//起始id
private long end = begin + 100000;//每次循环插入的数据量
private String url = "jdbc:mysql://localhost:3306/marketing?useServerPrepStmts=false&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8";
private String user = "root";
private String password = "123456";
public void insertBigData() {
//定义连接、statement对象
Connection conn = null;
PreparedStatement pstm = null;
try {
//加载jdbc驱动
Class.forName("com.mysql.jdbc.Driver");
//连接mysql
conn = DriverManager.getConnection(url, user, password);
//将自动提交关闭
// conn.setAutoCommit(false);
//编写sql
//String sql = "INSERT INTO t_send_message_send('plan_id', 'job_uuid','send_port','mobile','content','product_code','fake','date_push','activity_id') VALUES (?,?,?,?,?,?,?,?,?)";
String sql = "INSERT INTO t_send_message_send(plan_id,job_uuid,send_port,mobile,content,product_code,fake,date_push,activity_id) VALUES (?,?,?,?,?,?,?,?,?)";
//预编译sql
pstm = conn.prepareStatement(sql);
Calendar cal = Calendar.getInstance();
cal.setTime(new java.util.Date());
long phone = 13000000000L;
//开始总计时
long bTimeAll = System.currentTimeMillis();
//循环10次,每次十万数据,一共1000万
int i = 0;
for (; i < 1000; i++) {
java.sql.Date pushdatetime = new java.sql.Date(cal.getTime().getTime());
//开启分段计时,计1W数据耗时
long bTime = System.currentTimeMillis();
//开始循环
while (begin < end) {
//赋值
pstm.setLong(1, 123456789); //plan_id
pstm.setString(2, "9ccdb1d94e484cc8a477ddc2cc264c6c"); //job_uuid
pstm.setString(3, "10658098"); //send_port
pstm.setString(4, Long.toString(phone++));//mobile
pstm.setString(5, "益农控股(广东)有限公司( 下称“益农控股”)是由广东省农业农村厅按照国家农业农村部的要求,遴选的唯一一家省级“信息进村入户工程”的运营商。公司按照“省级运营商(益农控股)+县级运营中心+益农信息社”的三级运营模式,通过打造“一个平台+千万个益农信息社”");//content
pstm.setString(6, "HELP"); //product_code
pstm.setBoolean(7, false); //fake
pstm.setDate(8, pushdatetime);//date_push
pstm.setInt(9, 3);//activity_id
//添加到同一个批处理中
pstm.addBatch();
begin++;
}
//执行批处理
pstm.executeBatch();
end += 100000;
//关闭分段计时
long eTime = System.currentTimeMillis();
//减少一天
cal.add(Calendar.DATE, -1);
//输出
System.out.println("成功插入10W条数据耗时:" + (eTime - bTime));
}
//关闭总计时
long eTimeAll = System.currentTimeMillis();
//输出
System.out.println("插入10000W数据共耗时:" + (eTimeAll - bTimeAll));
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
}
实践证明确实很快,我的机器比较破,且表字段较原博主多,插入速度差不多每秒10000条,还可以。插入亿级数据差不多三四个小时。就我自己用了3个多小时,忘记截图了。
注意:
如果你的表建了索引,一定要先删掉,否则插入速度会越来越慢,慢到插入500W条数据也要半个小时,要插入亿级数据估计要到天荒地老了。数据插入完成后再建索引,重建索引也会花不少时间。就我自己而言,建了两个索引,一个varchar类型,一个datetime类型,建一个索引差不多二三十分钟。
总得来说,造亿级数据花4个小时,我已经很满意啦!