日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

如何快速向数据库插1000万数据?4种方法对比,它简单却速度最快

發布時間:2025/3/21 数据库 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何快速向数据库插1000万数据?4种方法对比,它简单却速度最快 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

一直有一種說法:批量插入大量數據到MySQL數據庫,不要使用Mybatis、Hibernate之類的ORM框架,原因一般都是說性能不好,至于為什么不好好像沒幾個人能講清楚的。

批量插入大量數據最優的方式是什么?網上也是眾說紛紜。不如自己動手測試一下吧!

場景介紹

前幾天公司項目進行壓力測試,測試某個功能在大數據量(千萬級)的情況下是否能夠正常運行,可是項目還沒有正式上線運營,數據庫里只有少量開發時用的假數據。

沒有數據怎么測試啊?這可愁壞測試的小姐姐們了,向我求助讓我盡快往數據庫中導入1000萬數據給她們測試用。

于是接到任務:快速往MySQL數據庫中導入1000萬數據

項目配置

啥也不說了,抓緊時間開搞!

首先交代一下電腦環境:

  • 操作系統:WIN10(專業版)
  • 開發工具:IntelliJ IDEA Ultimate(2019.2.1)
  • 項目框架:Spring Boot(2.2.5.RELEASE)
  • 數據庫:MySQL(5.7.27)

項目配置步驟:

1、使用IDEA的Spring Initializr插件新建Spring Boot的項目,打開pom.xml,添加一些必要的Maven依賴,主要是mybatis-spring-boot-starter和mysql-connector-java;

2、MySQL中新建一張user表,為了方便演示只保留id、昵稱、年齡3個字段,建表語句;

3、再次打開pom.xml文件,添加mybatis generator插件用于自動生成mapper映射文件;

4、上一步添加了mybatis generator插件之后還不能直接使用,還需要在項目resources目錄下新建一個配置文件generatorConfig.xml,里面主要需要配置數據庫連接信息、Model文件生成目錄、Mapper文件生成目錄、以及xml文件生成目錄;

5、打開resources目錄下的application.properties(或是application.yml)文件,添加一下mybatis相關配置和項目數據庫連接配置;

6、展示一下項目的完整結構

Mybatis為什么慢?

首先我們用Mybatis來測試一下,看看插入1000萬條數據需要多長時間。

實現步驟:

1、在UserMapper.java和UserMapper.xml文件中實現批量插入方法;

2、新建一個Test測試類實現隨機生成1000萬用戶記錄,并調用上步已經實現的批量插入方法將數據插入到MySQL數據庫;

接下來就是正式測試了,沒想到中間出了不少問題,在這里說明一下并附上解決方案。

問題一:Java堆內存爆了!

原因分析:由于要生成1000萬條用戶記錄,需要申請大量Java的堆內存,已經超出JVM設置的最大堆內存大小,導致OutOfMemoryError報錯:

解決辦法:增加堆內存。

JVM設置堆內存有兩個參數:

  • -Xms?用于設置堆內存初始值,一般建議設置為和最大值一樣;
  • -Xmx?用于設置堆內存最大值,默認值為物理內存的1/4;
  • 因為我的電腦是32G內存,也就是說默認最大堆內存有8G,8G都不夠的話,那我直接來個20G試試,IDEA菜單欄依次打開Run -> Edit Configurations:

    修改步驟:

  • 選中我們的測試類
  • 在右邊找到VM options選項,輸入-Xms20480m -Xmx20480m
  • 問題二:MySQL報錯:Packet for query is too large

    原因分析:因為發送到MySQL的數據量過大,超出了設置的最大值,導致報錯:

    解決方案:修改MySQL服務器max_allowed_packet屬性。

    修改步驟:

  • 直接在MySQL安裝目錄下找到my.ini文件,在[mysqld]下面添加一行max_allowed_packet = 4G
  • 通過MySQL客戶端工具修改,這里以我常用的MySQL Workbench客戶端來修改,菜單欄找到Server -> Options File,點擊切換Networking標簽:
  • Tip:不論哪種方式,修改完都要記得重啟MySQL,否則修改不生效哦。

    我們來看下執行結果:

    結果:

    使用Mybatis插入1000萬條數據到MySQL數據庫共花費了199.8秒

    這結果是快還是慢?我們來具體分析一下耗時分布情況。

    分析:

    方法:

    JDBC驅動中有一個profileSQL屬性,可以跟蹤記錄SQL執行時間,附上官方文檔介紹:

    所以我們需要將數據庫連接加上profileSQL=true屬性。

    再次看下執行結果:

    其中,duration指的是SQL執行的時間,也就是說MySQL服務器執行具體SQL語句的時間其實只有82.3秒,我們上面統計到Mybatis插入1000萬條數據花了近200秒的時間,那么這中間的100多秒都干嘛去了?

    分析控制臺輸出的日志之后我發現了蹊蹺所在:從程序調用Mybatis的批量插入方法開始,到MySQL服務器執行SQL,這中間正好差了100多秒,會是巧合嗎?

    打斷點Debug追蹤到Mybatis解析SQL語句的方法:

    這parse方法首先會讀取我們xml文件里的SQL模版拿到參數及參數類型信息,拼接生成SQL語句。

    每條數據循環一次,那1000W條數據就要循環解析1000萬次,不慢才怪!

    JdbcTemplate讓我眼前一亮

    接下來使用Spring框架的JdbcTemplate來測試一下。

    實現步驟:

  • 同樣的我們新建一個測試類,并用JdbcTemplate實現一個批量插入方法;
  • 接下來就可以開始測試了,果然中間又出現了了問題。

    問題一:調用JdbcTemplate的batchUpdate批量操作方法,結果卻一條條的插數據?

    首先看下控制臺輸出日志:

    可以看到JdbcTemplate是將我們的數據一條條的發送到MySQL服務器的,每個插入耗時1毫秒,那么1秒鐘可以插入1000條記錄,那么1000萬條數據就需要10000秒,大約需要2.78個小時。

    原因分析:JDBC驅動默認不支持批量操作,會將SQL語句分拆再一條條發往MySQL服務器執行,打斷點跟蹤一下代碼,看看是不是這樣:

    分析一下代碼:

    • 首先執行步驟1判斷rewriteBatchedStatements屬性,為false的話直接執行步驟5的邏輯:串行執行SQL語句,也就是一條條順序執行;
    • 如果rewriteBatchedStatements為true,那么首先會執行步驟2:判斷是否為insert語句,結果為true則會改寫SQL執行批量插入操作;
    • 如果不是insert語句,再繼續根據JDBC驅動版本以及數據量大小判斷是否需要執行批量操作;

    Tip:對于非insert的批量操作語句,如果數據量小于3條,那也只會一條條順序執行,不會進行合并批量執行。

    附上rewriteBatchedStatements官方文檔:

    大概看了一下,跟我們上面分析的一樣,標示是否讓JDBC驅動使用批量模式去改寫SQL語句。

    解決方案:數據庫連接上加上rewriteBatchedStatements=true屬性,開啟批量操作支持。

    再次看下執行結果:

    結果:

    使用JdbcTemplate插入1000萬條數據到MySQL數據庫共花費了80.1秒

    分析:

    一開始由于沒有開啟批量操作支持,所以導致MySQL只能一條條插入數據,原因在于我對JDBC驅動不夠了解,看來以后還得加強學習。

    開啟批量操作支持后,通過日志可以觀察到真正的SQL執行時間只有67.9秒,但整個插入操作用了80.1秒,中間差的10多秒中應該就是消耗在了改寫SQL語句上了。

    總得來說,JdbcTemplate批量插入大量數據的效率還不錯,讓我有眼前一亮的感覺。

    原生JDBC就是快啊!

    早有耳聞批量插入大量數據必須使用原生JDBC,百聞不如一見,接下來我就使用原生JDBC的方式來測試一下。

    實現步驟:

  • 同樣的,我們新建一個測試類,并使用原生JDBC的方式實現一個批量插入方法;
  • 接下來就可以測試了,別擔心,這次肯定不會再出問題了。

    來看下執行結果:

    結果:使用原生JDBC的方式插入1000萬條數據到MySQL數據庫共花費了58.9秒

    分析:

    原生JDBC寫起來還是既簡單又舒適啊,都多少年沒寫過了,但是越是簡單的東西它越好用。

    通過輸出日志,我們可以看到整個方法執行時間為58.9秒,而SQL真正的執行時間為46.8秒,中間同樣相差了10多秒,同樣也是花在了改寫SQL語句上,這一結果正好與上面JdbcTemplate的執行結果互相佐證,證明了我們的分析是正確的。

    存儲過程行不行?

    最后使用存儲過程的方式來試一下,說實話工作以來很少寫存儲過程,只好臨時惡補了一波知識。

    實現步驟:

  • 首先編寫批量插入的存儲過程,功能其實很簡單,接收一個外部傳入的表示循環次數的參數,進行循環插入數據;
  • 接下來我們調用存儲過程,執行命令:

    CALL batchInsert(10000000);

    等待執行完成,看下耗時情況:

    結果:

    調用存儲過程向MySQL數據庫中批量插入1000萬數據需要141.1秒

    分析:

    存儲過程需要141.1秒的時間我還是比較驚訝的,本來我對存儲過程還是比較期待的。

    仔細想想,其實存儲過程用在這個場景并沒有發揮出它的優勢,時間長點也不奇怪。

    為什么這么說?

    首先我們來看看存儲過程的一些特點:

  • 可以封裝一些復雜的業務邏輯,外部直接調用存儲過程即可;
  • 存儲過程只在創建時編譯一次,以后每次執行存儲過程都不需再重新編譯,使用存儲過程可提高執行速度;
  • 將操作直接放到數據庫端執行,可以減少客戶端與服務端進行網絡通訊開銷,提高通信效率;
  • 其次我們再來看看存儲過程用在我們場景是否合適:

  • 我們使一次性提交所有數據,所以不存在多次通信增加耗時的操作,在這里存儲過程的優勢沒有發揮出來;
  • 在存儲過程的insert語句中,我們使用了concat函數來拼接字符串,函數運算會降低SQL執行效率;
  • 所以說存儲過程在我們這個業務場景并沒有發揮出它的優勢。

    越簡單越快

    面對快速往MySQL數據庫中導入1000萬數據這個問題,我們通過Mybatis、JdbcTemplate、原生JDBC以及存儲過程4種方式分別進行測試,得出了最終結果:

    插入速度:原生JDBC > JdbcTemplate > 存儲過程 > Mybatis

    結果分析:

    Mybatis由于封裝程度較高,底層有一個SQL模版解析和SQL拼接的過程,所以導致速度較慢;

    存儲過程一來由于本應用場景不太適合沒有發揮出優勢,二來由于SQL語句中加入了函數運算拖累了執行效率;

    JdbcTemplate是Spring框架為了方便開發者調用對原生JDBC的一個輕度封裝,雖然有點小插曲,但整體來看插入效率還可以;

    原生JDBC是最最最基礎的插入方式了,每個人剛學Java的時候應該都學過,沒有過多花里胡哨的封裝,簡單實用。

    總結:

    越簡單越實用,原生JDBC第一名實至名歸!

    總結

    以上是生活随笔為你收集整理的如何快速向数据库插1000万数据?4种方法对比,它简单却速度最快的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲国产成人精品无码区99 | 欧美日韩高清一区二区 国产亚洲免费看 | 亚洲福利片| 亚洲AV无码一区二区伊人久久 | 91亚洲国产成人久久精品网站 | 可以在线观看的黄色 | 翔田千里一区二区 | 人妻互换免费中文字幕 | 强伦人妻一区二区三区 | 日韩淫| 老头糟蹋新婚少妇系列小说 | 国产干b | 久久国产在线观看 | 免费黄色一级 | 久久久国产视频 | 操综合 | 99精品久久久久久久 | 成人开心激情 | 永久免费AV无码网站韩国毛片 | 在线观看日韩一区二区 | 欧美孕交视频 | 最新av电影网站 | xxx国产精品 | 成人精品亚洲人成在线 | 欧美日韩综合 | 日本a v在线播放 | 天天做天天摸天天爽天天爱 | 久久久久久久久久久久Av | 国产麻豆一区二区 | 日本午夜免费福利视频 | 天天操夜夜拍 | 国产一级av毛片 | 日韩中文字幕在线视频 | 国产成人av一区二区三区在线观看 | 亚洲欧美激情小说另类 | 国产视频一区在线观看 | 亚洲精品中文字幕在线播放 | 亚洲日本在线观看 | 激情中文字幕 | 亚洲免费观看 | 久久久在线免费观看 | 久久成人福利视频 | 毛片最新网址 | 色乱码一区二区三在线看 | 久久不射电影网 | 久久天堂av综合合色蜜桃网 | 精品一级少妇久久久久久久 | 国产999精品 | 精品九九视频 | 老司机午夜影院 | 永久黄网站色视频免费观看w | jizzjizzjizz国产 | 天天干夜夜夜夜 | 国产经典一区 | 中国少妇无码专区 | 夜夜操综合 | 国内精品少妇 | 亚洲网站在线播放 | 亚洲日本中文字幕在线 | 免费a级片在线观看 | 午夜不卡久久精品无码免费 | 国产区av | 中文在线一区二区三区 | 97人妻精品一区二区三区视频 | 人人插插 | 久久精品资源 | 男女操网站 | 久久人妻无码aⅴ毛片a片app | 日韩第一页在线观看 | 伊人网视频在线观看 | 中文字幕在线观看一区 | 亚洲av无码国产精品久久久久 | 亚洲成人av片| wwwxx欧美| 日本xxxxxⅹxxxx69| www狠狠爱| 亚洲欧洲国产日韩 | 丁香色网 | 久久涩涩 | 国产第一区第二区 | 97午夜| 日韩字幕在线观看 | 亚欧激情 | 意大利性荡欲xxxxxx | 中文字幕免费在线观看 | 免费观看黄网站 | 日本免费在线观看视频 | 国产色吧| 国产精品国产成人国产三级 | 九九热在线免费视频 | 另类三区 | 麻豆传媒在线观看视频 | 精品人妻av一区二区 | 三级在线观看网站 | 护士的小嫩嫩好紧好爽 | 国产午夜三级 | 亚洲成人免费观看 | 欧美xx视频 | 日本少妇一级 |