今天来记录一下如何解决MybatisPlus导入数据过慢的问题,几点大概一年前就 遇到多这个问题,然后由于写这么一篇文章来记录,所以导致费了好大的功夫才找到之前的代码,真是好记性不如烂笔头。
首先说一下为什么使用MP批量导入上万条数据会比较慢,因为在MP中需要将对应的save方法转成sql语句,再去调用jdbc进行保存到数据库中。这里提一点,几乎任何框架都不能提高单个业务的速度,都是为了提高并发和开发效率而存在的。
所以我们的方法再简单不过了,就是回归到最原始的方法,使用jdbc直接手撸代码进行保存到数据库。下面的代码 大家肯定是既熟悉又陌生了,做了这么久开发了,几乎都不用手写jdbc了。
代码如下:
//数据源
@Autowired
private DataSource dataSource;
/**
* 批量新增,解决大量数据的性能问题
*
* @param questions
* @return
* @author 刘朋
* <br/>date 2022-07-25
*/
private void saveBatch(List<Question> questions) {
long t2 = System.currentTimeMillis();
Connection conn = null;
try {
conn = dataSource.getConnection();
conn.setAutoCommit(false);
// 批量插入
String sql2 = "INSERT INTO tb_question (index_id,ask_value,answer_value,answer_type,question_code_id,created_time,updated_time) VALUES (?,?,?,?,?,?,?)";
PreparedStatement pstm = conn.prepareStatement(sql2);
int count = 1;
long t = System.currentTimeMillis();
for (Question question : questions) {
pstm.setString(1, question.getIndexId());
pstm.setString(2, question.getAskValue());
pstm.setString(3, question.getAnswerValue());
pstm.setInt(4, question.getAnswerType());
pstm.setString(5, question.getQuestionCodeId());
pstm.setTimestamp(6, new Timestamp(t));
pstm.setTimestamp(7, new Timestamp(t));
// 把一个SQL命令加入命令列表
pstm.addBatch();
if (count % 5000 == 0) {
pstm.executeBatch();
}
count++;
}
// 执行批量更新
pstm.executeBatch();
pstm.close();
// 语句执行完毕提交事务
conn.commit();
} catch (Exception e) {
try {
if (conn != null) {
conn.rollback();
}
} catch (SQLException ex) {
log.warn("JDBC回滚异常!", ex);
throw new BaseException("JDBC回滚异常!请联系管理员!");
}
log.warn("SQL异常:" + e.getMessage(), e);
throw new BaseException("SQL异常,请联系管理员!");
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
log.warn("JDBC关闭异常!", e);
}
}
long t4 = System.currentTimeMillis();
log.info("插入数据库耗时:{}ms", (t4 - t2));
}
有了上面的代码性能问题就解决啦!