0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

MySQL批量插入數(shù)據(jù)的四種方案(性能測(cè)試對(duì)比)

Android編程精選 ? 來(lái)源:CSDN技術(shù)社區(qū) ? 作者:CSDN技術(shù)社區(qū) ? 2022-10-28 09:43 ? 次閱讀

本文記錄個(gè)人使用MySQL插入大數(shù)據(jù)總結(jié)較實(shí)用的方案,通過(guò)對(duì)常用插入大數(shù)據(jù)的4種方式進(jìn)行測(cè)試,即for循環(huán)單條、拼接SQL、批量插入saveBatch()、循環(huán) + 開(kāi)啟批處理模式,得出比較實(shí)用的方案心得。

一、前言

最近趁空閑之余,在對(duì)MySQL數(shù)據(jù)庫(kù)進(jìn)行插入數(shù)據(jù)測(cè)試,對(duì)于如何快速插入數(shù)據(jù)的操作無(wú)從下手,在僅1W數(shù)據(jù)量的情況下,竟花費(fèi)接近47s,實(shí)在不忍直視!在不斷摸索之后,整理出一些較實(shí)用的方案。

二、準(zhǔn)備工作

測(cè)試環(huán)境:SpringBoot項(xiàng)目、MyBatis-Plus框架、MySQL8.0.24、JDK13

前提:SpringBoot項(xiàng)目集成MyBatis-Plus上述文章有配置過(guò)程,同時(shí)實(shí)現(xiàn)IService接口用于進(jìn)行批量插入數(shù)據(jù)操作saveBatch()方法

1、Maven項(xiàng)目中pom.xml文件引入的相關(guān)依賴如下



 

org.springframework.boot
spring-boot-starter-web


 

com.baomidou
mybatis-plus-boot-starter
3.3.1


 

mysql
mysql-connector-java


 

org.projectlombok
lombok



2、application.yml配置屬性文件內(nèi)容(重點(diǎn):開(kāi)啟批處理模式)

server:
#端口號(hào)
port:8080

#MySQL連接配置信息(以下僅簡(jiǎn)單配置,更多設(shè)置可自行查看)
spring:
datasource:
#連接地址(解決UTF-8中文亂碼問(wèn)題+時(shí)區(qū)校正)
#(rewriteBatchedStatements=true開(kāi)啟批處理模式)
url:jdbc//127.0.0.1:3306/bjpowernode?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
#用戶名
username:root
#密碼
password:xxx
#連接驅(qū)動(dòng)名稱
driver-class-name:com.mysql.cj.jdbc.Driver

3、Entity實(shí)體類(lèi)(測(cè)試)

/**
*Student測(cè)試實(shí)體類(lèi)
*
*@Data注解:引入Lombok依賴,可省略Setter、Getter方法
*@authorLBF
*@date2022/3/1816:06
*/
@Data
@TableName(value="student")
publicclassStudent{

/**主鍵type:自增*/
@TableId(type=IdType.AUTO)
privateintid;

/**名字*/
privateStringname;

/**年齡*/
privateintage;

/**地址*/
privateStringaddr;

/**地址號(hào)@TableField:與表字段映射*/
@TableField(value="addr_num")
privateStringaddrNum;

publicStudent(Stringname,intage,Stringaddr,StringaddrNum){
this.name=name;
this.age=age;
this.addr=addr;
this.addrNum=addrNum;
}
}

4、數(shù)據(jù)庫(kù)student表結(jié)構(gòu)(注意:無(wú)索引)

f637d748-5608-11ed-a3b6-dac502259ad0.png

三、測(cè)試工作

簡(jiǎn)明:完成準(zhǔn)備工作后,即對(duì)for循環(huán)、拼接SQL語(yǔ)句、批量插入saveBatch()、循環(huán)插入+開(kāi)啟批處理模式,該4種插入數(shù)據(jù)的方式進(jìn)行測(cè)試性能。

注意:測(cè)試數(shù)據(jù)量為5W、單次測(cè)試完清空數(shù)據(jù)表(確保不受舊數(shù)據(jù)影響)

以下測(cè)試內(nèi)容可能受測(cè)試配置環(huán)境、測(cè)試規(guī)范和數(shù)據(jù)量等諸多因素影響,讀者可自行結(jié)合參考進(jìn)行測(cè)試

1、for循環(huán)插入(單條)(總耗時(shí):177秒)

總結(jié):測(cè)試平均時(shí)間約是177秒,實(shí)在是不忍直視(捂臉),因?yàn)槔胒or循環(huán)進(jìn)行單條插入時(shí),每次都是在獲取連接(Connection)、釋放連接和資源關(guān)閉等操作上,(如果數(shù)據(jù)量大的情況下)極其消耗資源,導(dǎo)致時(shí)間長(zhǎng)。

@GetMapping("/for")
publicvoidforSingle(){
//開(kāi)始時(shí)間
longstartTime=System.currentTimeMillis();
for(inti=0;i

(1)第一次測(cè)試結(jié)果:190155 約等于 190秒

f666ff0a-5608-11ed-a3b6-dac502259ad0.png

(2)第二次測(cè)試結(jié)果:175926 約等于 176秒(服務(wù)未重啟)

f67bef8c-5608-11ed-a3b6-dac502259ad0.png

(3)第三次測(cè)試結(jié)果:174726 約等于 174秒(服務(wù)重啟)

f69ac7e0-5608-11ed-a3b6-dac502259ad0.png

2、拼接SQL語(yǔ)句(總耗時(shí):2.9秒)

簡(jiǎn)明:拼接格式:insert into student(xxxx) value(xxxx),(xxxx),(xxxxx).......

總結(jié):拼接結(jié)果就是將所有的數(shù)據(jù)集成在一條SQL語(yǔ)句的value值上,其由于提交到服務(wù)器上的insert語(yǔ)句少了,網(wǎng)絡(luò)負(fù)載少了,性能也就提上去。

但是當(dāng)數(shù)據(jù)量上去后,可能會(huì)出現(xiàn)內(nèi)存溢出、解析SQL語(yǔ)句耗時(shí)等情況,但與第一點(diǎn)相比,提高了極大的性能。

@GetMapping("/sql")
publicvoidsql(){
ArrayListarrayList=newArrayList<>();
longstartTime=System.currentTimeMillis();
for(inti=0;i
//使用@Insert注解插入:此處為簡(jiǎn)便,不寫(xiě)Mapper.xml文件
@Insert("")
intinsertSplice(@Param("studentList")ListstudentList);

(1)第一次測(cè)試結(jié)果:3218 約等于 3.2秒

f6b57d9c-5608-11ed-a3b6-dac502259ad0.png

(2)第二次測(cè)試結(jié)果:2592 約等于 2.6秒(服務(wù)未重啟)

f6ccc786-5608-11ed-a3b6-dac502259ad0.png

(3)第三次測(cè)試結(jié)果:3082 約等于 3.1秒(服務(wù)重啟)

f6e4dfc4-5608-11ed-a3b6-dac502259ad0.png

3、批量插入saveBatch(總耗時(shí):2.7秒)

簡(jiǎn)明:使用MyBatis-Plus實(shí)現(xiàn)IService接口中批處理saveBatch()方法,對(duì)底層源碼進(jìn)行查看時(shí),可發(fā)現(xiàn)其實(shí)是for循環(huán)插入,但是與第一點(diǎn)相比,為什么性能上提高了呢?因?yàn)槔梅制幚恚╞atchSize = 1000) + 分批提交事務(wù)的操作,從而提高性能,并非在Connection上消耗性能。

@GetMapping("/saveBatch1")
publicvoidsaveBatch1(){
ArrayListarrayList=newArrayList<>();
longstartTime=System.currentTimeMillis();
//模擬數(shù)據(jù)
for(inti=0;i

(1)第一次測(cè)試結(jié)果:2864 約等于 2.9秒

f6f9376c-5608-11ed-a3b6-dac502259ad0.png

(2)第二次測(cè)試結(jié)果:2302 約等于 2.3秒(服務(wù)未重啟)

f711f1da-5608-11ed-a3b6-dac502259ad0.png

(3)第三次測(cè)試結(jié)果:2893 約等于 2.9秒(服務(wù)重啟)

f725f680-5608-11ed-a3b6-dac502259ad0.png

重點(diǎn)注意:MySQL JDBC驅(qū)動(dòng)默認(rèn)情況下忽略saveBatch()方法中的executeBatch()語(yǔ)句,將需要批量處理的一組SQL語(yǔ)句進(jìn)行拆散,執(zhí)行時(shí)一條一條給MySQL數(shù)據(jù)庫(kù),造成實(shí)際上是分片插入,即與單條插入方式相比,有提高,但是性能未能得到實(shí)質(zhì)性的提高。

測(cè)試:數(shù)據(jù)庫(kù)連接URL地址缺少 rewriteBatchedStatements = true 參數(shù)情況

#MySQL連接配置信息
spring:
datasource:
#連接地址(未開(kāi)啟批處理模式)
url:jdbc//127.0.0.1:3306/bjpowernode?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
#用戶名
username:root
#密碼
password:xxx
#連接驅(qū)動(dòng)名稱
driver-class-name:com.mysql.cj.jdbc.Driver

測(cè)試結(jié)果:10541 約等于 10.5秒(未開(kāi)啟批處理模式)

f737150a-5608-11ed-a3b6-dac502259ad0.png

4、循環(huán)插入 + 開(kāi)啟批處理模式(總耗時(shí):1.7秒)(重點(diǎn):一次性提交)

簡(jiǎn)明:開(kāi)啟批處理,關(guān)閉自動(dòng)提交事務(wù),共用同一個(gè)SqlSession之后,for循環(huán)單條插入的性能得到實(shí)質(zhì)性的提高;由于同一個(gè)SqlSession省去對(duì)資源相關(guān)操作的耗能、減少對(duì)事務(wù)處理的時(shí)間等,從而極大程度上提高執(zhí)行效率。(目前個(gè)人覺(jué)得最優(yōu)方案)

@GetMapping("/forSaveBatch")
publicvoidforSaveBatch(){
//開(kāi)啟批量處理模式BATCH、關(guān)閉自動(dòng)提交事務(wù)false
SqlSessionsqlSession=sqlSessionFactory.openSession(ExecutorType.BATCH,false);
//反射獲取,獲取Mapper
StudentMapperstudentMapper=sqlSession.getMapper(StudentMapper.class);
longstartTime=System.currentTimeMillis();
for(inti=0;i

(1)第一次測(cè)試結(jié)果:1831 約等于 1.8秒

f74cf744-5608-11ed-a3b6-dac502259ad0.png

(2)第二次測(cè)試結(jié)果:1382 約等于 1.4秒(服務(wù)未重啟)

f761abb2-5608-11ed-a3b6-dac502259ad0.png

(3)第三次測(cè)試結(jié)果:1883 約等于 1.9秒(服務(wù)重啟)

f776d226-5608-11ed-a3b6-dac502259ad0.png

四、總結(jié)

本文記錄個(gè)人學(xué)習(xí)MySQL插入大數(shù)據(jù)一些方案心得,可得知主要是在獲取連接、關(guān)閉連接、釋放資源和提交事務(wù)等方面較耗能,其中最需要注意是開(kāi)啟批處理模式,即URL地址的參數(shù):rewriteBatchedStatements = true,否則也無(wú)法發(fā)揮作用。

對(duì)于測(cè)試方案的設(shè)定、對(duì)考慮不周、理解和編寫(xiě)錯(cuò)誤的地方等情況,請(qǐng)多指出,共同學(xué)習(xí)!

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)庫(kù)
    +關(guān)注

    關(guān)注

    7

    文章

    3752

    瀏覽量

    64233
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    338

    瀏覽量

    14295
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    797

    瀏覽量

    26399

原文標(biāo)題:MySQL批量插入數(shù)據(jù)的四種方案(性能測(cè)試對(duì)比)

文章出處:【微信號(hào):AndroidPush,微信公眾號(hào):Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    FPGA 設(shè)計(jì)的四種常用思想與技巧

    FPGA 設(shè)計(jì)的四種常用思想與技巧FPGA設(shè)計(jì)的四種常用思想與技巧 討論的四種常用FPGA/CPLD設(shè)計(jì)思想與技巧:乒乓操作、串并轉(zhuǎn)換、流水線操作、數(shù)據(jù)接口同步化,都是FPGA/CP
    發(fā)表于 08-11 10:30

    數(shù)據(jù)四種思維方式

    數(shù)據(jù)所帶來(lái)的四種思維方式的轉(zhuǎn)變
    發(fā)表于 08-12 11:37

    labview插入數(shù)據(jù)MySQL數(shù)據(jù)庫(kù)

    最近在用labview寫(xiě)入數(shù)據(jù)MySQL數(shù)據(jù)庫(kù),遇到一個(gè)問(wèn)題:(如圖片所示)利用insert指令插入數(shù)據(jù),為什么每次
    發(fā)表于 12-26 16:52

    幾種數(shù)據(jù)庫(kù)的大數(shù)據(jù)批量插入解決方法

    在之前只知道SqlServer支持數(shù)據(jù)批量插入,殊不知道Oracle、SQLite和MySql也是支持的,不過(guò)Oracle需要使用Orace.DataAccess驅(qū)動(dòng),今天就貼出幾種
    發(fā)表于 11-04 07:59

    ModBus四種數(shù)據(jù)DI/DO/AI/AO是什么?

    ModBus四種數(shù)據(jù)DI/DO/AI/AO是什么?
    發(fā)表于 11-02 07:14

    測(cè)試比較四種Arduino Nano全新型號(hào)的數(shù)據(jù)詳細(xì)說(shuō)明

    本文檔的主要內(nèi)容詳細(xì)介紹的是測(cè)試比較四種Arduino Nano全新型號(hào)的數(shù)據(jù)詳細(xì)說(shuō)明。
    發(fā)表于 11-29 15:31 ?25次下載
    <b class='flag-5'>測(cè)試</b>比較<b class='flag-5'>四種</b>Arduino Nano全新型號(hào)的<b class='flag-5'>數(shù)據(jù)</b>詳細(xì)說(shuō)明

    MySQL數(shù)據(jù)庫(kù):如何操作禁止重復(fù)插入數(shù)據(jù)

    MySQL進(jìn)行數(shù)據(jù)插入操作時(shí),總是會(huì)考慮是否會(huì)插入重復(fù)數(shù)據(jù),之前的操作都是先根據(jù)主鍵或者唯一約束條件進(jìn)行查詢,有就進(jìn)行更新沒(méi)有就進(jìn)行
    的頭像 發(fā)表于 10-08 14:15 ?3273次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>數(shù)據(jù)</b>庫(kù):如何操作禁止重復(fù)<b class='flag-5'>插入</b><b class='flag-5'>數(shù)據(jù)</b>

    MySQL 5.7與MySQL 8.0 性能對(duì)比

    背景 測(cè)試mysql5.7和mysql8.0分別在讀寫(xiě),選定,只寫(xiě)模式下不同并發(fā)時(shí)的性能(tps,qps) 最早 測(cè)試使用版本為
    的頭像 發(fā)表于 11-03 09:26 ?1.6w次閱讀
    <b class='flag-5'>MySQL</b> 5.7與<b class='flag-5'>MySQL</b> 8.0 <b class='flag-5'>性能對(duì)比</b>

    四種門(mén)電路符號(hào)的詳細(xì)對(duì)比

    以下四種門(mén)電路符號(hào)對(duì)比,你更常用哪一
    發(fā)表于 02-09 17:05 ?1.4w次閱讀
    <b class='flag-5'>四種</b>門(mén)電路符號(hào)的詳細(xì)<b class='flag-5'>對(duì)比</b>

    MySQL 批量插入不重復(fù)數(shù)據(jù)的解決方法

    業(yè)務(wù)很簡(jiǎn)單:需要批量插入一些數(shù)據(jù),數(shù)據(jù)來(lái)源可能是其他數(shù)據(jù)庫(kù)的表,也可能是一個(gè)外部excel的導(dǎo)入
    的頭像 發(fā)表于 07-02 15:28 ?2248次閱讀
    <b class='flag-5'>MySQL</b> <b class='flag-5'>批量</b><b class='flag-5'>插入</b>不重復(fù)<b class='flag-5'>數(shù)據(jù)</b>的解決方法

    MyBatis批量插入數(shù)據(jù)的3方法你知道幾種

    批量插入功能是我們?nèi)粘9ぷ髦斜容^常見(jiàn)的業(yè)務(wù)功能之一, 今天 來(lái)一個(gè) MyBatis 批量插入的匯總篇,同時(shí)對(duì) 3 實(shí)現(xiàn)方法做一個(gè)
    的頭像 發(fā)表于 12-08 17:56 ?4202次閱讀
    MyBatis<b class='flag-5'>批量</b><b class='flag-5'>插入</b><b class='flag-5'>數(shù)據(jù)</b>的3<b class='flag-5'>種</b>方法你知道幾種

    目前HD地圖構(gòu)建的四種主流方案的優(yōu)勢(shì)與不足對(duì)比

    本文將帶領(lǐng)讀者深入探討這四種方案的優(yōu)勢(shì)與不足,通過(guò)對(duì)比方案來(lái)思考HD地圖構(gòu)建的重點(diǎn)與難點(diǎn)。當(dāng)然筆者水平有限,如果有理解錯(cuò)誤的地方歡迎大家一起討論,共同學(xué)習(xí)。 溫馨提示,本文討論的方案
    的頭像 發(fā)表于 12-12 10:26 ?3075次閱讀

    MySQL在執(zhí)行批量操作的時(shí)候一次插入多少數(shù)據(jù)才合適呢?

    我們?cè)诓僮鞔笮?b class='flag-5'>數(shù)據(jù)表或者日志文件的時(shí)候經(jīng)常會(huì)需要寫(xiě)入數(shù)據(jù)數(shù)據(jù)庫(kù),那么最合適的方案就是數(shù)據(jù)庫(kù)的批量
    的頭像 發(fā)表于 01-31 14:09 ?7510次閱讀

    NoSQL數(shù)據(jù)庫(kù)的四種類(lèi)型

    在本文中,我們將簡(jiǎn)要介紹NoSQL數(shù)據(jù)庫(kù)的四種類(lèi)型。
    的頭像 發(fā)表于 04-25 17:21 ?4243次閱讀

    測(cè)試電容器的四種方法有哪些

    測(cè)試電容器的四種方法 電容器是一非常常見(jiàn)的電子元件,它具有存儲(chǔ)電能的能力。測(cè)試電容器的方法也非常多,下面我們將詳細(xì)介紹四種常見(jiàn)的
    的頭像 發(fā)表于 09-01 15:11 ?1.3w次閱讀