Java百萬級數(shù)據(jù)存入MySql

我又來了,又是百萬數(shù)據(jù)的導(dǎo)入,其實(shí)又是項(xiàng)目中遇到的,那么怎么快速導(dǎo)入呢,因?yàn)槲覀冺?xiàng)目用的是JPA,有時(shí)也使用jdbcTemplate,沒錯(cuò)又是jdbcTemplate。對于這種大數(shù)據(jù)的處理,我們能業(yè)務(wù)代碼方面最基本的能想到的就是塊處理和使用線程。此處可以參考JAVA向Mysql插入億級別數(shù)據(jù)---測評


首先由于我們項(xiàng)目用的是jpa,so我最先也使用的jpa來存數(shù)據(jù),而且最先做的也是批量處理,一次存10000數(shù)據(jù)。在springboot1.5中,jpa的save有兩個(gè)方法,先來看一下源碼:

@NoRepositoryBean
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {
    <S extends T> S save(S var1);
    <S extends T> Iterable<S> save(Iterable<S> var1);
}

可以看到save既可以保存一個(gè)實(shí)體,也可以保存多個(gè)實(shí)體,所以我選擇的就是保存多個(gè)實(shí)體,結(jié)果發(fā)現(xiàn)save的速度賊慢,尤其是想存100000條數(shù)據(jù)時(shí)。而如果我save單個(gè)實(shí)體,并開啟多線程,發(fā)現(xiàn)save的效率比批量處理要快點(diǎn),我也是懵了。一開始就這樣存80多萬的數(shù)據(jù)用了N久,具體時(shí)間也沒記錄了。

然后自己就想著用最原生的方法來存一下,就是jdbc,同樣一次存10000條,批量處理。

首先要注意的是:
1.在URL連接時(shí)需要開啟批處理、以及預(yù)編譯
String url = “jdbc:mysql://localhost:3306/cds_credit_rtm_data?rewriteBatched
-Statements=true&useServerPrepStmts=false”;

  1. PreparedStatement預(yù)處理sql語句必須放在循環(huán)體外

接下來就是常規(guī)的jdbc操作:

//開始總計(jì)時(shí)
long bTime1 = System.currentTimeMillis();
//count=1380271
for (int i=0; i<count; i+=100000){
   List<DataToEmployee> list = //todo 每次從數(shù)據(jù)庫獲取10w條
   Connection conn = null;
   PreparedStatement pstm = null;
  try{
    //加載jdbc驅(qū)動(dòng)
    Class.forName("com.mysql.jdbc.Driver");
    //連接mysql
    conn = DriverManager.getConnection(url, user, password);
    String sql = ".....";  //insert語句
     //關(guān)閉自動(dòng)提交
//  conn.setAutoCommit(false);
    //預(yù)編譯sql
    pstm = conn.prepareStatement(sql);
    if(list!=null && list.size()>0){
        long bTime = System.currentTimeMillis();
        for(DataToEmployee data : list){
            pstm.setString(1,data.getName());
            ......
            pstm.addBatch();  //批量處理
        }
        pstm.executeBatch();
        //關(guān)閉分段計(jì)時(shí)
       long eTime = System.currentTimeMillis();
       //輸出
       System.out.println("成功插入10W條數(shù)據(jù)耗時(shí):"+(eTime-bTime));
    }
  }
}
//關(guān)閉總計(jì)時(shí)
long eTime1 = System.currentTimeMillis();
//輸出
System.out.println("插入"+count+"數(shù)據(jù)共耗時(shí):"+(eTime1-bTime1));

這里統(tǒng)計(jì)出插入10W條數(shù)據(jù)的時(shí)間一般維持在2s左右,相比之前jpa是有很大的提升

成功插入10W條數(shù)據(jù)耗時(shí):2832
成功插入10W條數(shù)據(jù)耗時(shí):1870
成功插入10W條數(shù)據(jù)耗時(shí):2328
成功插入10W條數(shù)據(jù)耗時(shí):2023
成功插入10W條數(shù)據(jù)耗時(shí):2148
成功插入10W條數(shù)據(jù)耗時(shí):1789
成功插入10W條數(shù)據(jù)耗時(shí):1987
成功插入10W條數(shù)據(jù)耗時(shí):2032
...

jpa在存大量數(shù)據(jù)的時(shí)候,需要進(jìn)行ORM轉(zhuǎn)換,MyBatis也一樣,效率相比jdbc肯定要差點(diǎn),而且在使用jdbc的時(shí)候我就用了單線程,可見兩者之間的差距。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容