在平常工做中,咱们常常会遇到各类各样的需求,须要将数据插入到数据库中,不过不一样的需求用不一样的插入写法,这样能提高很大的效率,这篇文章会根据不一样的场景使用不一样的批量插入代码,你们之后遇到批量插入直接来我这里粘贴就能够了。java
场景一:sql
app中最多见的pv和uv接口,用户每点击一次都须要在数据库中插入一条数据。这种状况咱们不可能一直请求数据库,确定会将数据先存到缓存或者队列中,而后批量插入到数据库。数据库
上队列代码缓存
public void run() { startLog(); while (!isInterrupted()) { List<T> list = new ArrayList<T>(); preProcessor(); try { long ts = 0; //每一百条批量插入一次 for (int i = 0; i < 100; ) { T tmp = null; try { tmp = queue.poll(5000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { e.printStackTrace(); } if (tmp != null) { //记录第一次添加数据后的时间 if (i++ == 0) { ts = System.currentTimeMillis(); } //处理 processor(list, tmp); continue; } //有数据 且从第一次插入数据已通过了 设定时间 则 执行插入 if (list.size() > 0 && System.currentTimeMillis() - ts >= BATCH_TIMEOUT) { break; } } save(list); } catch (Exception e) { e.printStackTrace(); } } }
上mybatis代码session
<insert id="batchInsert" parameterType="List"> insert into dsc_user ( user_name, nick_name, mobile ) values <foreach collection='list' item='item' index='index' separator=','> ( #{item.userName,jdbcType=VARCHAR},#{item.nickName,jdbcType=VARCHAR},#{item.mobile,jdbcType=VARCHAR} ) </foreach> </insert>
注:这个地方不能把foreach标签写到外层,不然仍是会不停的建立关闭sqlsessionmybatis
场景二:app
某个功能导入数据老是千万级别,如何最快的将数据插入到数据库中ide
这种大数据量导入数据 和 小数据量导入是有很大区别的,一样的代码,小数据量导入能够完美实现,但数据量大了以后就会出现各类各样的问题大数据
首先,咱们要重视的是内存,若是要实现千万级别的数据导入,JVM的堆内存必定要设置一个比较大的数值url
其次,要分段保存到数据库,好比每1000条数据执行一次
最后,不要使用mybatis,由于myabtis封装程度过高,解析SQL模板和SQL拼接会消耗大量时间,要使用原生的JDBC
上代码
public void insertBatch() { Connection conn = null; Statement statement = null; try { conn = DriverManager.getConnection(url, username, password); conn.setAutoCommit(false); statement = conn.createStatement(); for (int i = 0; i < 10000000; i++) { String sql = "insert into dsc_user(user_name, nick_name, mobile) values ('"+i+"', '第"+i+"条数据', '158'+"+ i +")"; //利用addBatch方法将SQL语句加入到stmt对象中 statement.addBatch(sql); if (i % 1000 == 0 && i != 0) { //利用executeBatch方法执行1000条SQL语句 statement.executeBatch(); statement.clearBatch(); conn.commit(); } } statement.executeBatch(); statement.clearBatch(); conn.commit(); close(); //关闭资源 } catch (SQLException e) { e.printStackTrace(); } }
通常状况下,咱们不多遇到须要批量插入千万级别数据的,因此批量插入只须要在mybatis中使用一下foreach标签就能解决,以下代码
public void insertBatch(List<CouponHistory> coupons){ if (coupons == null || coupons.isEmpty()){ return; } int index = 1000; int currentPageStart = 0; int currentPageEnd = 0; while (currentPageEnd < coupons.size()){ currentPageStart = currentPageEnd; currentPageEnd = Math.min(currentPageEnd + index, coupons.size()); //调用mybatis批量插入 batchInsert(coupons.subList(currentPageStart, currentPageEnd)); } }
<insert id="batchInsert" parameterType="List"> insert into dsc_user ( user_name, nick_name, mobile ) values <foreach collection='list' item='item' index='index' separator=','> ( #{item.userName,jdbcType=VARCHAR},#{item.nickName,jdbcType=VARCHAR},#{item.mobile,jdbcType=VARCHAR} ) </foreach> </insert>
你们在作批量插入时只须要将最后这块代码复制过去就能够啦
注:mybatis-plus中批量插入方法就是 for循环单条插入;
以上就是批量导入两个场景中的解决方案,今天就写到这里,再见啦!
昔我往矣,杨柳依依
今我来思,雨雪霏霏
【白话译文】
回想当初出征时,杨柳依依随风吹;现在回来路途中,大雪纷纷满天飞