在平常工做中,咱們常常會遇到各類各樣的需求,須要將數據插入到數據庫中,不過不一樣的需求用不一樣的插入寫法,這樣能提高很大的效率,這篇文章會根據不一樣的場景使用不一樣的批量插入代碼,你們之後遇到批量插入直接來我這裏粘貼就能夠了。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循環單條插入;
以上就是批量導入兩個場景中的解決方案,今天就寫到這裏,再見啦!
昔我往矣,楊柳依依
今我來思,雨雪霏霏
【白話譯文】
回想當初出征時,楊柳依依隨風吹;現在回來路途中,大雪紛紛滿天飛