2019獨角獸企業重金招聘Python工程師標準>>>
因前段時間去面試,問到如何高效向數據庫插入10萬條記錄,之前沒處理過類似問題,也沒看過相關資料,結果沒答上來,今天就查了些資料,總結出三種方法:
測試數據庫為mysql!!!
方法一:
?
[java]?view plain?copy
- public?static?void?insert()?{??
- ????????//?開時時間??
- ????????Long?begin?=?new?Date().getTime();??
- ????????//?sql前綴??
- ????????String?prefix?=?"INSERT?INTO?tb_big_data?(count,?create_time,?random)?VALUES?";??
- ????????try?{??
- ????????????//?保存sql后綴??
- ????????????StringBuffer?suffix?=?new?StringBuffer();??
- ????????????//?設置事務為非自動提交??
- ????????????conn.setAutoCommit(false);??
- ????????????//?Statement?st?=?conn.createStatement();??
- ????????????//?比起st,pst會更好些??
- ????????????PreparedStatement?pst?=?conn.prepareStatement("");??
- ????????????//?外層循環,總提交事務次數??
- ????????????for?(int?i?=?1;?i?<=?100;?i++)?{??
- ????????????????//?第次提交步長??
- ????????????????for?(int?j?=?1;?j?<=?10000;?j++)?{??
- ????????????????????//?構建sql后綴??
- ????????????????????suffix.append("("?+?j?*?i?+?",?SYSDATE(),?"?+?i?*?j??
- ????????????????????????????*?Math.random()?+?"),");??
- ????????????????}??
- ????????????????//?構建完整sql??
- ????????????????String?sql?=?prefix?+?suffix.substring(0,?suffix.length()?-?1);??
- ????????????????//?添加執行sql??
- ????????????????pst.addBatch(sql);??
- ????????????????//?執行操作??
- ????????????????pst.executeBatch();??
- ????????????????//?提交事務??
- ????????????????conn.commit();??
- ????????????????//?清空上一次添加的數據??
- ????????????????suffix?=?new?StringBuffer();??
- ????????????}??
- ????????????//?頭等連接??
- ????????????pst.close();??
- ????????????conn.close();??
- ????????}?catch?(SQLException?e)?{??
- ????????????e.printStackTrace();??
- ????????}??
- ????????//?結束時間??
- ????????Long?end?=?new?Date().getTime();??
- ????????//?耗時??
- ????????System.out.println("cast?:?"?+?(end?-?begin)?/?1000?+?"?ms");??
- ????}??
?
?
輸出時間:cast : 23 ms
該方法目前測試是效率最高的方法!
?
?
?
方法二:
?
[java]?view plain?copy
- public?static?void?insertRelease()?{??
- ????????Long?begin?=?new?Date().getTime();??
- ????????String?sql?=?"INSERT?INTO?tb_big_data?(count,?create_time,?random)?VALUES?(?,?SYSDATE(),??)";??
- ????????try?{??
- ????????????conn.setAutoCommit(false);??
- ????????????PreparedStatement?pst?=?conn.prepareStatement(sql);??
- ????????????for?(int?i?=?1;?i?<=?100;?i++)?{??
- ????????????????for?(int?k?=?1;?k?<=?10000;?k++)?{??
- ????????????????????pst.setLong(1,?k?*?i);??
- ????????????????????pst.setLong(2,?k?*?i);??
- ????????????????????pst.addBatch();??
- ????????????????}??
- ????????????????pst.executeBatch();??
- ????????????????conn.commit();??
- ????????????}??
- ????????????pst.close();??
- ????????????conn.close();??
- ????????}?catch?(SQLException?e)?{??
- ????????????e.printStackTrace();??
- ????????}??
- ????????Long?end?=?new?Date().getTime();??
- ????????System.out.println("cast?:?"?+?(end?-?begin)?/?1000?+?"?ms");??
- ????}??
?
注:注釋就沒有了,和上面類同,下面會有分析!
控制臺輸出:cast : 111 ms
執行時間是上面方法的5倍!
?
?
方法三:
?
[java]?view plain?copy
- public?static?void?insertBigData(SpringBatchHandler?sbh)?{??
- ????????Long?begin?=?new?Date().getTime();??
- ????????JdbcTemplate?jdbcTemplate?=?sbh.getJdbcTemplate();??
- ????????final?int?count?=?10000;??
- ????????String?sql?=?"INSERT?INTO?tb_big_data?(count,?create_time,?random)?VALUES?(?,?SYSDATE(),??)";??
- ????????jdbcTemplate.batchUpdate(sql,?new?BatchPreparedStatementSetter()?{??
- ????????????//?為prepared?statement設置參數。這個方法將在整個過程中被調用的次數??
- ????????????public?void?setValues(PreparedStatement?pst,?int?i)??
- ????????????????????throws?SQLException?{??
- ????????????????pst.setLong(1,?i);??
- ????????????????pst.setInt(2,?i);??
- ????????????}??
- ??
- ????????????//?返回更新的結果集條數??
- ????????????public?int?getBatchSize()?{??
- ????????????????return?count;??
- ????????????}??
- ????????});??
- ????????Long?end?=?new?Date().getTime();??
- ????????System.out.println("cast?:?"?+?(end?-?begin)?/?1000?+?"?ms");??
- ????}??
該方法采用的是spring batchUpdate執行,因效率問題,數據量只有1萬條!
?
執行時間:cast : 387 ms
?
?
?
?
總結:方法一和方法二很類同,唯一不同的是方法一采用的是“insert into tb (...) values(...),(...)...;”的方式執行插入操作,
方法二則是“insert into tb (...) values (...);insert into tb (...) values (...);...”的方式,要不是測試,我也不知道兩者差別是如此之大!
當然,這個只是目前的測試,具體執行時間和步長也有很大關系!如過把步長改為100,可能方法就要幾分鐘了吧,這個可以自己測試哈。。。
方法三網上很推崇,不過,效率大家也都看到了,1萬條記錄,耗時6分鐘,可見其效率并不理想!而且方法三需要配置spring applicationContext環境才能應用!
不過,方法三在ssh/spring-mvc中可用性還是很高的!
?
剛才開始研究大數據方面的問題,以上也只是真實測試的結果,并不一定就是事實,有好的建議,大家請指正,謝謝!
相互學習,才能進步更快!
?
晚點會把源碼發上來,大家可以直接去下載測試!