mysql中批量插入數(shù)據(jù)(1萬(wàn)、10萬(wàn)、100萬(wàn)、1000萬(wàn)、1億級(jí)別)
硬件:windows7+8G內(nèi)存+i3-4170處理器+4核CPU
首先貼上數(shù)據(jù)庫(kù)的操作類(lèi)BaseDao:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import com.lk.entity.TUser; public class BaseDao { private static ConfigManager cm = ConfigManager.getInstance(); private static String Driver = null; private static String URL = null; private static String USER = null; private static String PWD = null; private static Connection conn = null; private static PreparedStatement psmt = null; public ResultSet rs = null; public int row = 0; static { Driver = cm.getString("DRIVER"); URL = cm.getString("URL"); USER = cm.getString("USER"); PWD = cm.getString("PWD"); try { Class.forName(Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } getConnection(); try { conn.setAutoCommit(false); psmt = conn.prepareStatement(""); } catch (SQLException e) { e.printStackTrace(); } } private static Connection getConnection() { try { conn = DriverManager.getConnection(URL, USER, PWD); } catch (SQLException e) { e.printStackTrace(); } return conn; } /** * 多條記錄插入操作 * flag是為了判斷是否是插入的最后一個(gè)記錄 */ public boolean affectRowMore(String sql, List<TUser> list, long flag) { try { psmt = conn.prepareStatement(sql); for (TUser tUser : list) { psmt.setLong(1, tUser.getId()); psmt.setString(2, tUser.getName()); psmt.setInt(3, tUser.getSex()); psmt.setString(4, tUser.getPhone()); psmt.setString(5, tUser.getPassword()); // 添加執(zhí)行sql psmt.addBatch(); } // 執(zhí)行操作 int[] counts = psmt.executeBatch(); // 執(zhí)行Batch中的全部語(yǔ)句 conn.commit(); // 提交到數(shù)據(jù)庫(kù) for (int i : counts) { if (i == 0) { conn.rollback(); } } closeAll(flag); } catch (SQLException e) { e.printStackTrace(); return false; } return true; } /** * 多條記錄插入操作 */ public boolean affectRowMore1(String sql, long flag) { try { psmt.addBatch(sql); // 執(zhí)行操作 int[] counts = psmt.executeBatch(); // 執(zhí)行Batch中的全部語(yǔ)句 conn.commit(); // 提交到數(shù)據(jù)庫(kù) for (int i : counts) { if (i == 0) { conn.rollback(); return false; } } closeAll(flag); } catch (SQLException e) { e.printStackTrace(); return false; } return true; } public void closeAll(long flag) { try { if (conn != null && flag == -1) { // 在完成批量操作后恢復(fù)默認(rèn)的自動(dòng)提交方式,提高程序的可擴(kuò)展性 conn.setAutoCommit(true); conn.close(); } if (psmt != null && flag == -1) { psmt.close(); } if (rs != null) { rs.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
方法一:
通過(guò)BaseDao中的affectRowMore方法進(jìn)行插入,插入的速度如下所示:
* 一萬(wàn)條數(shù)據(jù)(通過(guò)多條添加)
* 生成1萬(wàn)條數(shù)據(jù)共花費(fèi)978毫秒
* 生成10萬(wàn)條數(shù)據(jù)共花費(fèi)5826毫秒
* 生成100萬(wàn)條數(shù)據(jù)共花費(fèi)54929毫秒
* 生成1000萬(wàn)條數(shù)據(jù)共花費(fèi)548640毫秒
* 生成1億條數(shù)據(jù)(因?yàn)閿?shù)字過(guò)大,沒(méi)有計(jì)算)
public void insertBenchMark() { ?? ??? ?long start = System.currentTimeMillis(); ?? ??? ?List<TUser> list = new ArrayList<>(); ?? ??? ?long row = 1; ?? ??? ?for (int j = 0; j < 1000; j++) { ?? ??? ??? ?for (int i = 0; i < 10000; i++) { ?? ??? ??? ??? ?String uuid = UUID.randomUUID().toString(); ?? ??? ??? ??? ?String name = uuid.substring(0, 4); ?? ??? ??? ??? ?int sex = -1; ?? ??? ??? ??? ?if(Math.random() < 0.51) { ?? ??? ??? ??? ??? ?sex = 1; ?? ??? ??? ??? ?}else { ?? ??? ??? ??? ??? ?sex = 0; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?String phone = (String) RandomValue.getAddress().get("tel"); ?? ??? ??? ??? ?list.add(new TUser(row,name, sex, phone, uuid)); ?? ??? ??? ??? ?row++; ?? ??? ??? ?} ?? ??? ??? ?int flag = 1; ?? ??? ??? ?if(j==999) { ?? ??? ??? ??? ?flag = -1; ?? ??? ??? ?} ?? ??? ??? ?//封裝好的 ?? ??? ??? ?boolean b = userDao.insertMore(list,flag); ?? ??? ??? ?if(!b) { ?? ??? ??? ??? ?System.out.println("出錯(cuò)了----"); ?? ??? ??? ??? ?System.exit(0); ?? ??? ??? ?}else { ?? ??? ??? ??? ?list.clear(); ?? ??? ??? ?} ?? ??? ?} ?? ??? ?long end = System.currentTimeMillis(); ?? ??? ?System.out.println("生成1000萬(wàn)條數(shù)據(jù)共花費(fèi)"+(end-start)+"毫秒"); ?? ?} public boolean insertMore(List<TUser> list,long flag) { ?? ??? ?String sql = "insert into tuser(id,name,sex,phone,password) values(?,?,?,?,?)"; ?? ??? ?return affectRowMore(sql,list,flag); ?? ?}
方法二:
通過(guò)BaseDao中的affectRowMore1方法進(jìn)行數(shù)據(jù)的插入操作,插入的速度如下:
* 通過(guò)拼接語(yǔ)句實(shí)現(xiàn)多條添加
* 生成1萬(wàn)條數(shù)據(jù)共花費(fèi)225毫秒
* 生成10萬(wàn)條數(shù)據(jù)共花費(fèi)1586毫秒
* 生成100萬(wàn)條數(shù)據(jù)共花費(fèi)14017毫秒
* 生成1000萬(wàn)條數(shù)據(jù)共花費(fèi)152127毫秒
* 生成1億條數(shù)據(jù)(因?yàn)閿?shù)字過(guò)大,沒(méi)有計(jì)算)
public void insertBenchMark1() { ?? ??? ?long start = System.currentTimeMillis(); ?? ??? ?StringBuffer suffix = new StringBuffer(); ?? ??? ?long row = 1; ?? ??? ?for (int j = 0; j < 1000; j++) { ?? ??? ??? ?for (int i = 0; i < 10000; i++) { ?? ??? ??? ??? ?String uuid = UUID.randomUUID().toString(); ?? ??? ??? ??? ?String name = uuid.substring(0, 4); ?? ??? ??? ??? ?int sex = -1; ?? ??? ??? ??? ?if(Math.random() < 0.51) { ?? ??? ??? ??? ??? ?sex = 1; ?? ??? ??? ??? ?}else { ?? ??? ??? ??? ??? ?sex = 0; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?String phone = (String) RandomValue.getAddress().get("tel"); ?? ??? ??? ??? ?suffix.append("(" + row + ",'" + name + "'," + sex + ",'" + phone + "','" + uuid + "'),"); ?? ??? ??? ??? ?row++; ?? ??? ??? ?} ?? ??? ??? ?boolean b = userDao.insertMore1(suffix.substring(0, suffix.length()-1),j); ?? ??? ??? ?if(!b) { ?? ??? ??? ??? ?System.out.println("出錯(cuò)了----"); ?? ??? ??? ??? ?System.exit(0); ?? ??? ??? ?}else { ?? ??? ??? ??? ?// 清空上一次添加的數(shù)據(jù) ?? ??? ??? ??? ?suffix = new StringBuffer(); ?? ??? ??? ?} ?? ??? ?} ?? ??? ?long end = System.currentTimeMillis(); ?? ??? ?System.out.println("生成1000萬(wàn)條數(shù)據(jù)共花費(fèi)"+(end-start)+"毫秒"); ?? ?} public boolean insertMore1(String sql_suffix,long flag) { ?? ??? ?String sql_prefix = "insert into tuser(id,name,sex,phone,password) values "; ?? ??? ?return affectRowMore1(sql_prefix + sql_suffix,flag); ?? ?}
總結(jié):
方法一和方法二很類(lèi)同,唯一不同的是方法一采用的是“insert into tb (...) values (...);insert into tb (...) values (...);...”的方式執(zhí)行插入操作,方法二則是“insert into tb (...) values(...),(...)...;”的方式。
通過(guò)測(cè)試的對(duì)比,方法二比方法一快了近5倍。
到此這篇關(guān)于mysql中批量插入數(shù)據(jù)(1萬(wàn)、10萬(wàn)、100萬(wàn)、1000萬(wàn)、1億級(jí)別)的文章就介紹到這了,更多相關(guān)mysql 批量插入數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SQL如何使用正則表達(dá)式對(duì)數(shù)據(jù)進(jìn)行過(guò)濾
正則表達(dá)式的作用是匹配文本,將一個(gè)正則表達(dá)式與一個(gè)文本串進(jìn)行比較,下面這篇文章主要給大家介紹了關(guān)于SQL如何使用正則表達(dá)式對(duì)數(shù)據(jù)進(jìn)行過(guò)濾的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09關(guān)于mysql時(shí)間區(qū)間問(wèn)題淺析
在很多地方都使用到了mysql的日期查詢(xún),下面這篇文章主要給大家介紹了關(guān)于mysql時(shí)間區(qū)間問(wèn)題的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04mysql 存儲(chǔ)過(guò)程判斷重復(fù)的不插入數(shù)據(jù)
這篇文章主要介紹了下面是一個(gè)較常見(jiàn)的場(chǎng)景,判斷表中某列是否存在某值,如果存在執(zhí)行某操作,需要的朋友可以參考下2017-01-01MySQL存儲(chǔ)過(guò)程和函數(shù)的操作(十二)
這篇文章主要為大家詳細(xì)介紹了MySQL存儲(chǔ)過(guò)程和函數(shù)的操作第十二篇,感興趣的小伙伴們可以參考一下2016-08-08MySQL自動(dòng)停機(jī)的問(wèn)題處理實(shí)戰(zhàn)記錄
這篇文章主要給大家介紹了關(guān)于MySQL自動(dòng)停機(jī)的問(wèn)題處理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用MySQL具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05mysql8.0.20配合binlog2sql的配置和簡(jiǎn)單備份恢復(fù)的步驟詳解
這篇文章主要介紹了mysql8.0.20配合binlog2sql的配置和簡(jiǎn)單備份恢復(fù)的步驟,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09在Ubuntu或Debian系統(tǒng)的服務(wù)器上卸載MySQL的方法
這篇文章主要介紹了在Ubuntu或Debian系統(tǒng)的服務(wù)器上卸載MySQL的方法,適用于Debian系的Linux系統(tǒng),需要的朋友可以參考下2015-06-06