因前段時間去面試,,問到如何高效向數(shù)據(jù)庫插入10萬條記錄,,之前沒處理過類似問題,,也沒看過相關(guān)資料,結(jié)果沒答上來,,今天就查了些資料,,總結(jié)出三種方法:
測試數(shù)據(jù)庫為MySQL!!!
方法一:
- 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();
- // 設(shè)置事務(wù)為非自動提交
- conn.setAutoCommit(false);
- // Statement st = conn.createStatement();
- // 比起st,pst會更好些
- PreparedStatement pst = conn.prepareStatement("");
- // 外層循環(huán),,總提交事務(wù)次數(shù)
- for (int i = 1; i <= 100; i++) {
- // 第次提交步長
- for (int j = 1; j <= 10000; j++) {
- // 構(gòu)建sql后綴
- suffix.append("(" + j * i + ", SYSDATE(), " + i * j
- * Math.random() + "),");
- }
- // 構(gòu)建完整sql
- String sql = prefix + suffix.substring(0, suffix.length() - 1);
- // 添加執(zhí)行sql
- pst.addBatch(sql);
- // 執(zhí)行操作
- pst.executeBatch();
- // 提交事務(wù)
- conn.commit();
- // 清空上一次添加的數(shù)據(jù)
- suffix = new StringBuffer();
- }
- // 頭等連接
- pst.close();
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- // 結(jié)束時間
- Long end = new Date().getTime();
- // 耗時
- System.out.println("cast : " + (end - begin) / 1000 + " ms");
- }
輸出時間:cast : 23 ms
該方法目前測試是效率最高的方法!
方法二:
- 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
執(zhí)行時間是上面方法的5倍,!
方法三:
- 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設(shè)置參數(shù)。這個方法將在整個過程中被調(diào)用的次數(shù)
- public void setValues(PreparedStatement pst, int i)
- throws SQLException {
- pst.setLong(1, i);
- pst.setInt(2, i);
- }
-
- // 返回更新的結(jié)果集條數(shù)
- public int getBatchSize() {
- return count;
- }
- });
- Long end = new Date().getTime();
- System.out.println("cast : " + (end - begin) / 1000 + " ms");
- }
該方法采用的是spring batchUpdate執(zhí)行,,因效率問題,,數(shù)據(jù)量只有1萬條!
執(zhí)行時間:cast : 387 ms
總結(jié):方法一和方法二很類同,,唯一不同的是方法一采用的是“insert into tb (...) values(...),(...)...;”的方式執(zhí)行插入操作,,
方法二則是“insert into tb (...) values (...);insert into tb (...) values (...);...”的方式,要不是測試,我也不知道兩者差別是如此之大,!
當(dāng)然,,這個只是目前的測試,具體執(zhí)行時間和步長也有很大關(guān)系,!如過把步長改為100,,可能方法就要幾分鐘了吧,這個可以自己測試哈,。,。。
方法三網(wǎng)上很推崇,,不過,,效率大家也都看到了,1萬條記錄,,耗時6分鐘,,可見其效率并不理想!而且方法三需要配置spring applicationContext環(huán)境才能應(yīng)用,!
不過,,方法三在ssh/spring-mvc中可用性還是很高的!
剛才開始研究大數(shù)據(jù)方面的問題,,以上也只是真實(shí)測試的結(jié)果,,并不一定就是事實(shí),有好的建議,,大家請指正,,謝謝!
相互學(xué)習(xí),,才能進(jìn)步更快,!
晚點(diǎn)會把源碼發(fā)上來,大家可以直接去下載測試,!
|