前言
最近在项目上遇到了批量插入的场景问题,由于每次需要插入超过 10w+ 的数据量并且字段也蛮多的导致如果使用循环单次插入的方式插入数据插入的效率不高。相信读者们在实际开发中也遇到过这样类似的场景,那么批量插入如何实现呢?
其实我也是一知半解,之前只见过别人博客上的批量插入实现,对于实际优化上的细节以及优化的程度并不了解。所以正好借此机会,在这里认真地把批量插入的实现及优化过程实操一遍并记录下来,有兴趣的读者们可以接着往下观看,有不对的地方还希望能在评论里指出来。
既然涉及到了数据库层面的操作,我想从 JDBC 和 MyBatis / MyBatis Plus 两个层面分别实现一下批量插入,下面将依次讲解实现及优化过程。
JDBC 实现批量插入
在编写代码前,先准备一下 JDBC 批量插入需要的测试环境。
JDBC 测试环境
建表语句(使用数据库版本 mysql 5.7.19)
DROP TABLE IF EXISTS `fee`;
CREATE TABLE `fee` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`owner` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '归属人',
`fee1` decimal(30, 5) NULL DEFAULT NULL COMMENT '费用1',
`fee2` decimal(30, 5) NULL DEFAULT NULL COMMENT '费用2',
`fee3` decimal(30, 5) NULL DEFAULT NULL COMMENT '费用3',
`fee4` decimal(30, 5) NULL DEFAULT NULL COMMENT '费用4',
`fee5` decimal(30, 5) NULL DEFAULT NULL COMMENT '费用5',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '费用表' ROW_FORMAT = Dynamic;
maven 坐标(使用 Java 版本 JDK 1.8)
mysql
mysql-connector-java
5.1.9
普通插入
在实现批量插入之前呢,为了更明显的看到普通插入方式和批量插入方式的不同,先来写一遍普通插入(循环插入)的实现并记录一下插入所需时间。
使用 JDBC 不需要添加额外的配置文件,直接上代码:
/**
* JDBC - 普通插入(循环遍历一条一条插入)
* @author 单程车票
*/
public class JDBCDemo {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "123456";
String driver = "com.mysql.jdbc.Driver";
// sql语句
String sql = "INSERT INTO fee(`owner`,`fee1`,`fee2`,`fee3`,`fee4`,`fee5`) VALUES (?,?,?,?,?,?);";
Connection conn = null;
PreparedStatement ps = null;
// 开始时间
long start = System.currentTimeMillis();
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
ps = conn.prepareStatement(sql);
// 循环遍历插入数据
for (int i = 1; i