<cite id="ffb66"></cite><cite id="ffb66"><track id="ffb66"></track></cite>
      <legend id="ffb66"><li id="ffb66"></li></legend>
      色婷婷久,激情色播,久久久无码专区,亚洲中文字幕av,国产成人A片,av无码免费,精品久久国产,99视频精品3
      網易首頁 > 網易號 > 正文 申請入駐

      13 秒插入 30 萬條數據,這才是批量插入正確的姿勢!

      0
      分享至

      Java精選面試題(微信小程序):5000+道面試題和選擇題,包含Java基礎、并發、JVM、線程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架構設計、大廠真題等,在線隨時刷題!

      本文主要講述通過MyBatis、JDBC等做大數據量數據插入的案例和結果。

      30萬條數據插入插入數據庫驗證

      • 實體類、mapper和配置文件定義

        • User實體

        • mapper接口

        • mapper.xml文件

        • jdbc.properties

        • sqlMapConfig.xml

      • 不分批次直接梭哈

      • 循環逐條插入

      • MyBatis實現插入30萬條數據

      • JDBC實現插入30萬條數據

      • 總結

      驗證的數據庫表結構如下:

      CREATE TABLE `t_user` (   `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶id',   `username` varchar(64) DEFAULT NULL COMMENT '用戶名稱',   `age` int(4) DEFAULT NULL COMMENT '年齡',   PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶信息表';

      話不多說,開整!

      實體類、mapper和配置文件定義

      User實體

      /**  * 用戶實體  *  * @Author zjq  */ @Data public class User {     private int id;     private String username;     private int age; }

      mapper接口

      public interface UserMapper {     /**      * 批量插入用戶      * @param userList      */     void batchInsertUser(@Param("list") List userList); }

      mapper.xml文件

      "batchInsertUser"  parameterType= "java.util.List" >     insert into t_user(username,age) values     "list"  item= "item"  index= "index"  separator= "," >         (          #{item.username},          #{item.age}         )    

      jdbc.properties

      jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test jdbc.username=root jdbc.password=root

      sqlMapConfig.xml

      "1.0" encoding="UTF-8" ?> "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">         "jdbc.properties" >                 type = "com.zjq.domain.User" alias = "user" >             "developement" >         "developement" >             type = "JDBC" >             type = "POOLED" >                 "driver"  value= "${jdbc.driver}" />                 "url"  value= "${jdbc.url}" />                 "username"  value= "${jdbc.username}" />                 "password"  value= "${jdbc.password}" />                                         "com/zjq/mapper/UserMapper.xml" >    

      不分批次直接梭哈

      MyBatis直接一次性批量插入30萬條,代碼如下:

      @Test public void testBatchInsertUser() throws IOException {     InputStream resourceAsStream =             Resources.getResourceAsStream("sqlMapConfig.xml");     SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);     SqlSession session = sqlSessionFactory.openSession();     System.out.println("===== 開始插入數據 =====");     long startTime = System.currentTimeMillis();     try {         List userList = new ArrayList<>();         for (int i = 1; i <= 300000; i++) {             User user = new User();             user.setId(i);             user.setUsername("共飲一杯無 " + i);             user.setAge((int) (Math.random() * 100));             userList.add(user);         }         session.insert("batchInsertUser", userList); // 最后插入剩余的數據         session.commit();         long spendTime = System.currentTimeMillis()-startTime;         System.out.println("成功插入 30 萬條數據,耗時:"+spendTime+"毫秒");     } finally {         session.close();     } }

      可以看到控制臺輸出:

      Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (27759038 >yun 4194304). You can change this value on the server by setting the max_allowed_packet’ variable.


      圖片

      超出最大數據包限制了,可以通過調整max_allowed_packet限制來提高可以傳輸的內容,不過由于30萬條數據超出太多,這個不可取,梭哈看來是不行了

      既然梭哈不行那我們就一條一條循環著插入行不行呢

      循環逐條插入

      mapper接口和mapper文件中新增單個用戶新增的內容如下:

      /**  * 新增單個用戶  * @param user  */ void insertUser(User user); "insertUser"  parameterType= "user" >     insert into t_user(username,age) values         (          #{username},          #{age}         )

      調整執行代碼如下:

      @Test public void testCirculateInsertUser() throws IOException {     InputStream resourceAsStream =             Resources.getResourceAsStream("sqlMapConfig.xml");     SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);     SqlSession session = sqlSessionFactory.openSession();     System.out.println("===== 開始插入數據 =====");     long startTime = System.currentTimeMillis();     try {         for (int i = 1; i <= 300000; i++) {             User user = new User();             user.setId(i);             user.setUsername("共飲一杯無 " + i);             user.setAge((int) (Math.random() * 100));             // 一條一條新增             session.insert("insertUser", user);             session.commit();         }         long spendTime = System.currentTimeMillis()-startTime;         System.out.println("成功插入 30 萬條數據,耗時:"+spendTime+"毫秒");     } finally {         session.close();     } }

      執行后可以發現磁盤IO占比飆升,一直處于高位。


      圖片

      等啊等等啊等,好久還沒執行完


      圖片

      先不管他了太慢了先搞其他的,等會再來看看結果吧。

      two thousand year later …

      控制臺輸出如下:


      圖片

      總共執行了14909367毫秒,換算出來是4小時八分鐘。太慢了。。


      圖片

      還是優化下之前的批處理方案吧

      MyBatis實現插入30萬條數據

      先清理表數據,然后優化批處理執行插入:

      -- 清空用戶表 TRUNCATE table  t_user;

      以下是通過 MyBatis 實現 30 萬條數據插入代碼實現:

      /**  * 分批次批量插入  * @throws IOException  */ @Test public void testBatchInsertUser() throws IOException {     InputStream resourceAsStream =             Resources.getResourceAsStream("sqlMapConfig.xml");     SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);     SqlSession session = sqlSessionFactory.openSession();     System.out.println("===== 開始插入數據 =====");     long startTime = System.currentTimeMillis();     int waitTime = 10;     try {         List userList = new ArrayList<>();         for (int i = 1; i <= 300000; i++) {             User user = new User();             user.setId(i);             user.setUsername("共飲一杯無 " + i);             user.setAge((int) (Math.random() * 100));             userList.add(user);             if (i % 1000 == 0) {                 session.insert("batchInsertUser", userList);                 // 每 1000 條數據提交一次事務                 session.commit();                 userList.clear();                 // 等待一段時間                 Thread.sleep(waitTime * 1000);             }         }         // 最后插入剩余的數據         if(!CollectionUtils.isEmpty(userList)) {             session.insert("batchInsertUser", userList);             session.commit();         }         long spendTime = System.currentTimeMillis()-startTime;         System.out.println("成功插入 30 萬條數據,耗時:"+spendTime+"毫秒");     } catch (Exception e) {         e.printStackTrace();     } finally {         session.close();     } }

      使用了 MyBatis 的批處理操作,將每 1000 條數據放在一個批次中插入,能夠較為有效地提高插入速度。同時請注意在循環插入時要帶有合適的等待時間和批處理大小,以防止出現內存占用過高等問題。此外,還需要在配置文件中設置合理的連接池和數據庫的參數,以獲得更好的性能。


      圖片

      在上面的示例中,我們每插入1000行數據就進行一次批處理提交,并等待10秒鐘。這有助于控制內存占用,并確保插入操作平穩進行。


      圖片

      五十分鐘執行完畢,時間主要用在了等待上。

      如果低谷時期執行,CPU和磁盤性能又足夠的情況下,直接批處理不等待執行:

      /**  * 分批次批量插入  * @throws IOException  */ @Test public void testBatchInsertUser() throws IOException {     InputStream resourceAsStream =             Resources.getResourceAsStream("sqlMapConfig.xml");     SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);     SqlSession session = sqlSessionFactory.openSession();     System.out.println("===== 開始插入數據 =====");     long startTime = System.currentTimeMillis();     int waitTime = 10;     try {         List userList = new ArrayList<>();         for (int i = 1; i <= 300000; i++) {             User user = new User();             user.setId(i);             user.setUsername("共飲一杯無 " + i);             user.setAge((int) (Math.random() * 100));             userList.add(user);             if (i % 1000 == 0) {                 session.insert("batchInsertUser", userList);                 // 每 1000 條數據提交一次事務                 session.commit();                 userList.clear();             }         }         // 最后插入剩余的數據         if(!CollectionUtils.isEmpty(userList)) {             session.insert("batchInsertUser", userList);             session.commit();         }         long spendTime = System.currentTimeMillis()-startTime;         System.out.println("成功插入 30 萬條數據,耗時:"+spendTime+"毫秒");     } catch (Exception e) {         e.printStackTrace();     } finally {         session.close();     } }

      則24秒可以完成數據插入操作:


      圖片圖片

      可以看到短時CPU和磁盤占用會飆高。

      把批處理的量再調大一些調到5000,在執行:


      圖片

      13秒插入成功30萬條,直接蕪湖起飛

      JDBC實現插入30萬條數據

      JDBC循環插入的話跟上面的mybatis逐條插入類似,不再贅述。

      以下是 Java 使用 JDBC 批處理實現 30 萬條數據插入的示例代碼。請注意,該代碼僅提供思路,具體實現需根據實際情況進行修改。

      /**  * JDBC分批次批量插入  * @throws IOException  */ @Test public void testJDBCBatchInsertUser() throws IOException {     Connection connection = null;     PreparedStatement preparedStatement = null;     String databaseURL = "jdbc:mysql://localhost:3306/test";     String user = "root";     String password = "root";     try {         connection = DriverManager.getConnection(databaseURL, user, password);         // 關閉自動提交事務,改為手動提交         connection.setAutoCommit(false);         System.out.println("===== 開始插入數據 =====");         long startTime = System.currentTimeMillis();         String sqlInsert = "INSERT INTO t_user ( username, age) VALUES ( ?, ?)";         preparedStatement = connection.prepareStatement(sqlInsert);         Random random = new Random();         for (int i = 1; i <= 300000; i++) {             preparedStatement.setString(1, "共飲一杯無 " + i);             preparedStatement.setInt(2, random.nextInt(100));             // 添加到批處理中             preparedStatement.addBatch();             if (i % 1000 == 0) {                 // 每1000條數據提交一次                 preparedStatement.executeBatch();                 connection.commit();                 System.out.println("成功插入第 "+ i+" 條數據");             }         }         // 處理剩余的數據         preparedStatement.executeBatch();         connection.commit();         long spendTime = System.currentTimeMillis()-startTime;         System.out.println("成功插入 30 萬條數據,耗時:"+spendTime+"毫秒");     } catch (SQLException e) {         System.out.println("Error: " + e.getMessage());     } finally {         if (preparedStatement != null) {             try {                 preparedStatement.close();             } catch (SQLException e) {                 e.printStackTrace();             }         }         if (connection != null) {             try {                 connection.close();             } catch (SQLException e) {                 e.printStackTrace();             }         }     } }
      圖片圖片

      上述示例代碼中,我們通過 JDBC 連接 MySQL 數據庫,并執行批處理操作插入數據。具體實現步驟如下:

      • 獲取數據庫連接。

      • 創建 Statement 對象。

      • 定義 SQL 語句,使用PreparedStatement對象預編譯 SQL 語句并設置參數。

      • 執行批處理操作。

      • 處理剩余的數據。

      • 關閉 Statement 和 Connection 對象。

      使用setAutoCommit(false)來禁止自動提交事務,然后在每次批量插入之后手動提交事務。每次插入數據時都新建一個PreparedStatement對象以避免狀態不一致問題。在插入數據的循環中,每 10000 條數據就執行一次executeBatch()插入數據。

      另外,需要根據實際情況優化連接池和數據庫的相關配置,以防止連接超時等問題。

      總結

      實現高效的大量數據插入需要結合以下優化策略(建議綜合使用):

      1.批處理:批量提交SQL語句可以降低網絡傳輸和處理開銷,減少與數據庫交互的次數。在Java中可以使用Statement或者PreparedStatementaddBatch()方法來添加多個SQL語句,然后一次性執行executeBatch()方法提交批處理的SQL語句。

      • 在循環插入時帶有適當的等待時間和批處理大小,從而避免內存占用過高等問題:

        • 設置適當的批處理大小:批處理大小指在一次插入操作中插入多少行數據。如果批處理大小太小,插入操作的頻率將很高,而如果批處理大小太大,可能會導致內存占用過高。通常,建議將批處理大小設置為1000-5000行,這將減少插入操作的頻率并降低內存占用。

        • 采用適當的等待時間:等待時間指在批處理操作之間等待的時間量。等待時間過短可能會導致內存占用過高,而等待時間過長則可能會延遲插入操作的速度。通常,建議將等待時間設置為幾秒鐘到幾十秒鐘之間,這將使操作變得平滑且避免出現內存占用過高等問題。

        • 可以考慮使用一些內存優化的技巧,例如使用內存數據庫或使用游標方式插入數據,以減少內存占用。

      • 總的來說,選擇適當的批處理大小和等待時間可以幫助您平穩地進行插入操作,避免出現內存占用過高等問題。

      2.索引:在大量數據插入前暫時去掉索引,最后再打上,這樣可以大大減少寫入時候的更新索引的時間。

      3.數據庫連接池:使用數據庫連接池可以減少數據庫連接建立和關閉的開銷,提高性能。在沒有使用數據庫連接池的情況,記得在finally中關閉相關連接。

      數據庫參數調整:增加MySQL數據庫緩沖區大小、配置高性能的磁盤和I/O等。

      來源:https://blog.csdn.net/qq_35427589/article/details/129665307

      公眾號“Java精選”所發表內容注明來源的,版權歸原出處所有(無法查證版權的或者未注明出處的均來自網絡,系轉載,轉載的目的在于傳遞更多信息,版權屬于原作者。如有侵權,請聯系,筆者會第一時間刪除處理!

      最近有很多人問,有沒有讀者交流群!加入方式很簡單,公眾號Java精選,回復“加群”,即可入群!

      文章有幫助的話,點在看,轉發吧!

      特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。

      Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

      相關推薦
      熱點推薦
      總有人納悶,王健林就算只剩100億,為啥王思聰花錢還是那么大方

      總有人納悶,王健林就算只剩100億,為啥王思聰花錢還是那么大方

      小光侃娛樂
      2025-12-10 22:10:04
      瓜帥:我不想以被解雇的方式離開,我想好好結束

      瓜帥:我不想以被解雇的方式離開,我想好好結束

      懂球帝
      2025-12-20 15:09:22
      何穗忙完工作一天也不想帶娃!回家換完衣跑去看展覽,當媽后多愁

      何穗忙完工作一天也不想帶娃!回家換完衣跑去看展覽,當媽后多愁

      趕山的姑娘
      2025-12-20 21:23:24
      湘潭一村民組開會決議將“外嫁女”所得法院執行款項從其親屬頭上扣除,村支書:對決議不知情,未簽字批準

      湘潭一村民組開會決議將“外嫁女”所得法院執行款項從其親屬頭上扣除,村支書:對決議不知情,未簽字批準

      紅星新聞
      2025-12-20 00:33:11
      北京阿姨20年守茅臺股票:90萬本金,分紅326萬,成本歸零!

      北京阿姨20年守茅臺股票:90萬本金,分紅326萬,成本歸零!

      趣文說娛
      2025-12-20 18:29:20
      少一人仍不輸,47歲蘭帕德率隊1-1,狂攬48分領跑+領先米堡6分

      少一人仍不輸,47歲蘭帕德率隊1-1,狂攬48分領跑+領先米堡6分

      側身凌空斬
      2025-12-20 22:31:10
      上海迪士尼突發一幕,演出被迫中斷!網友:她還在笑,心太大了

      上海迪士尼突發一幕,演出被迫中斷!網友:她還在笑,心太大了

      環球網資訊
      2025-12-20 09:29:14
      我外交部突然發出警告,如果外媒消息屬實,中日事態將會相當嚴重

      我外交部突然發出警告,如果外媒消息屬實,中日事態將會相當嚴重

      芊芊子吟
      2025-12-20 14:07:18
      人類文明現在只有0.73級,宇宙中的7級文明有多可怕?

      人類文明現在只有0.73級,宇宙中的7級文明有多可怕?

      觀察宇宙
      2025-12-20 20:55:31
      金正恩做出重大舉動,矛頭直指高市早苗

      金正恩做出重大舉動,矛頭直指高市早苗

      回京歷史夢
      2025-12-21 02:40:04
      阿房宮遺址考古取得突破性進展

      阿房宮遺址考古取得突破性進展

      環球網資訊
      2025-12-20 15:09:09
      金毛事件大反轉!為減刑出賣白三姐,20萬轉賬記錄撕開人性遮羞布

      金毛事件大反轉!為減刑出賣白三姐,20萬轉賬記錄撕開人性遮羞布

      魔都姐姐雜談
      2025-12-20 04:48:09
      咖啡再次被關注!醫生發現:高血壓患者經常喝咖啡,或有5改善

      咖啡再次被關注!醫生發現:高血壓患者經常喝咖啡,或有5改善

      牛鍋巴小釩
      2025-12-20 16:45:23
      中央明確規定:從明年起,將對普通高中進行擴招。

      中央明確規定:從明年起,將對普通高中進行擴招。

      百態人間
      2025-12-18 05:00:04
      于東來回應高薪招聘英才:哪怕年薪2000萬都無所謂,給的不是財富,是尊重

      于東來回應高薪招聘英才:哪怕年薪2000萬都無所謂,給的不是財富,是尊重

      都市快報橙柿互動
      2025-12-20 11:30:57
      努諾:丟球過早讓一切變得困難,幾個丟球我們都可以做得更好

      努諾:丟球過早讓一切變得困難,幾個丟球我們都可以做得更好

      懂球帝
      2025-12-21 02:00:07
      王楚欽傳來壞消息:背傷診斷結果曝光!林詩棟17天打3站,不休息

      王楚欽傳來壞消息:背傷診斷結果曝光!林詩棟17天打3站,不休息

      侃球熊弟
      2025-12-20 00:15:03
      池莉:半輩子過去了,自己盡是不體面和不高貴,遍體鱗傷

      池莉:半輩子過去了,自己盡是不體面和不高貴,遍體鱗傷

      尚曦讀史
      2025-12-18 09:46:21
      市監局通報“南極磷蝦油”事件:已成立聯合調查組進駐北京同仁堂(四川)健康藥業有限公司開展調查,已對該企業立案

      市監局通報“南極磷蝦油”事件:已成立聯合調查組進駐北京同仁堂(四川)健康藥業有限公司開展調查,已對該企業立案

      極目新聞
      2025-12-20 19:28:56
      底層無貴人,社交無意義

      底層無貴人,社交無意義

      詩詞中國
      2025-12-19 20:34:22
      2025-12-21 03:40:49
      Java精選
      Java精選
      一場永遠也演不完的戲
      1764文章數 3859關注度
      往期回顧 全部

      科技要聞

      許四清:具身智能的"ChatGPT時刻"還未到來

      頭條要聞

      臺北致4人身亡嫌犯被指是"大陸籍" 蔣萬安回應

      頭條要聞

      臺北致4人身亡嫌犯被指是"大陸籍" 蔣萬安回應

      體育要聞

      我開了20年大巴,現在是一名西甲主帥

      娛樂要聞

      2026央視跨年晚會陣容曝光,豪華陣仗

      財經要聞

      求解“地方財政困難”

      汽車要聞

      嵐圖推進L3量產測試 已完成11萬公里實際道路驗證

      態度原創

      家居
      房產
      健康
      教育
      軍事航空

      家居要聞

      高端私宅 理想隱居圣地

      房產要聞

      廣州有態度,一座國際化社區給出的城市答案

      這些新療法,讓化療不再那么痛苦

      教育要聞

      別逼孩子死磕高二數學了!我用3個“懶方法”,讓倒數娃沖進前20

      軍事要聞

      澤連斯基:前線局勢愈發艱難

      無障礙瀏覽 進入關懷版 主站蜘蛛池模板: 99久久99久久精品免费看蜜桃| 精品国产女同疯狂摩擦2| 色吊丝av中文字幕| 2020精品自拍视频曝光| 亚洲熟妇无码爱v在线观看| 传媒视频??高清一区传媒| 亚洲熟妇丰满大屁股熟妇| 丰满人妻中文字幕无码| 欧美a√| 浴室人妻的情欲hd三级国产 | 亚洲精品无码高潮喷水在线| 97超碰人人| 日韩亚洲欧美中文在线| 亚洲在线成人网| 亚洲国产午夜精品理论片| 亚洲国产精品久久久久秋霞影院 | 亚洲精品无amm毛片| 国产精品久久久久7777按摩| 日日噜噜夜夜久久亚洲一区二区| 精品久久久久久无码中文字幕一区| 91亚色| 狠狠躁夜夜躁人人爽天天bl| 人妻久久Aⅴ| 国产精品v欧美精品∨日韩 | 内射后入在线观看一区| jizzjizz亚洲| 日本高清熟妇老熟妇| 中文字幕熟女人妻丝袜| 成人A在线播放| 内地自拍三级在线观看| 日韩一区二区三区无码影院| 99热视屏| 日本高清在线播放一区二区三区| 午夜羞羞影院男女爽爽爽| 亚洲中文字幕人妻| 无码av在线播放| 女人的精水喷出来视频| 精品成a人无码| 亚洲熟女视讯2| 精品久久人人妻人人做精品| 中文字幕无码不卡一区二区三区|