日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

MyBatis批量插入數(shù)據(jù)優(yōu)化,那叫一個優(yōu)雅!

來源: 責(zé)編: 時間:2024-01-02 09:30:34 225觀看
導(dǎo)讀在項目開發(fā)中,我們經(jīng)常需要進行大量數(shù)據(jù)的批量插入操作。然而,在實際應(yīng)用中,插入大量數(shù)據(jù)時性能常常成為一個瓶頸。在我最近的項目中,我發(fā)現(xiàn)了一些能夠顯著提升批量插入性能的方法,并進行了一系列實驗來驗證它們的有效性。

在項目開發(fā)中,我們經(jīng)常需要進行大量數(shù)據(jù)的批量插入操作。然而,在實際應(yīng)用中,插入大量數(shù)據(jù)時性能常常成為一個瓶頸。在我最近的項目中,我發(fā)現(xiàn)了一些能夠顯著提升批量插入性能的方法,并進行了一系列實驗來驗證它們的有效性。wO528資訊網(wǎng)——每日最新資訊28at.com

今日內(nèi)容介紹,大約花費15分鐘wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

背景介紹

我們使用了 mybatis-plus 框架,并采用其中的 saveBatch 方法進行批量數(shù)據(jù)插入。然而,通過深入研究源碼,我發(fā)現(xiàn)這個方法并沒有如我期望的那樣高效wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

這是因為最終在執(zhí)行的時候還是通過for循環(huán)一條條執(zhí)行insert,然后再一批的進行flush ,默認(rèn)批的消息為1000wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

為了找到更優(yōu)秀的解決方案,我展開了一場性能優(yōu)化的探索之旅。好了我們現(xiàn)在開始探索wO528資訊網(wǎng)——每日最新資訊28at.com

實驗準(zhǔn)備

  • 創(chuàng)建一張表tb_student
create table springboot_mp.tb_student(    id      bigint auto_increment comment '主鍵ID'        primary key,    stuid   varchar(40)   not null comment '學(xué)號',    name    varchar(30)   null comment '姓名',    age     tinyint       null comment '年齡',    sex     tinyint(1)    null comment '性別 0 男 1 女',    dept    varchar(2000) null comment '院系',    address varchar(400)  null comment '家庭地址',    constraint stuid        unique (stuid));
  • 創(chuàng)建spring-boot-mybatis-demo項目并在pom.xml中添加依賴

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

<dependencies>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-test</artifactId>    </dependency>    <dependency>        <groupId>mysql</groupId>        <artifactId>mysql-connector-java</artifactId>        <version>8.0.30</version>    </dependency>    <dependency>        <groupId>com.baomidou</groupId>        <artifactId>mybatis-plus-boot-starter</artifactId>        <version>3.5.3</version>    </dependency>    <dependency>        <groupId>org.projectlombok</groupId>        <artifactId>lombok</artifactId>    </dependency></dependencies>
  • application.yml配置
server:  port: 8890spring:  application:    name: mybatis-demo #指定服務(wù)名  datasource:    username: root    password: root#    url: jdbc:mysql://localhost:3306/springboot_mp?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true    url: jdbc:mysql://localhost:3306/springboot_mp?useUnicode=true&characterEncoding=utf8    driver-class-name: com.mysql.cj.jdbc.Driver#mybatis-plus:  configuration:    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  mapper-locations: classpath*:/mapper/**/*.xml
  • 使用mybatisX生成代碼

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

探索實驗

每次都是插入100000條數(shù)據(jù)wO528資訊網(wǎng)——每日最新資訊28at.com

注意:因為我的電腦性能比較好,所以才插入這么多數(shù)據(jù),大家可以插入1000進行實驗對比wO528資訊網(wǎng)——每日最新資訊28at.com

  1. 單條循環(huán)插入:傳統(tǒng)方法的基準(zhǔn)

首先,我采用了傳統(tǒng)的單條循環(huán)插入方法,將每條數(shù)據(jù)逐一插入數(shù)據(jù)庫,作為性能對比的基準(zhǔn)。wO528資訊網(wǎng)——每日最新資訊28at.com

/** * @author springboot葵花寶典 * @description: TODO */@SpringBootTestpublic class MybatisTest {    @Autowired    private StudentService studentService;    @Autowired    private SqlSessionFactory sqlSessionFactory;    @Test    public void MybatisBatchSaveOneByOne(){        SqlSession sqlSession = sqlSessionFactory.openSession();        try {            StopWatch stopWatch = new StopWatch();            stopWatch.start("mybatis plus save one");            for (int i = 0; i < 100000; i++) {                Student student = new Student();                student.setStuid("6840"+i);                student.setName("zhangsan"+i);                student.setAge((i%100));                if(i%2==0){                    student.setSex(0);                }else {                    student.setSex(1);                }                student.setDept("計算機學(xué)院");                student.setAddress("廣東省廣州市番禺"+i+"號");                //一條一條插入                studentService.save(student);            }            sqlSession.commit();            stopWatch.stop();            System.out.println("mybatis plus save one:" + stopWatch.getTotalTimeMillis());        } finally {            sqlSession.close();        }    }}

發(fā)現(xiàn)花費了195569毫秒wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

  1. mybatis-plus 的 saveBatch 方法

現(xiàn)在嘗試 mybatis-plus 提供的 saveBatch 方法,期望它能夠提高性能。wO528資訊網(wǎng)——每日最新資訊28at.com

@Test    public void MybatissaveBatch(){        SqlSession sqlSession = sqlSessionFactory.openSession();        try {            List<Student> students = new ArrayList<>();            StopWatch stopWatch = new StopWatch();            stopWatch.start("mybatis plus save batch");            for (int i = 0; i < 100000; i++) {                Student student = new Student();                student.setStuid("6840"+i);                student.setName("zhangsan"+i);                student.setAge((i%100));                if(i%2==0){                    student.setSex(0);                }else {                    student.setSex(1);                }                student.setDept("計算機學(xué)院");                student.setAddress("廣東省廣州市番禺"+i+"號");                //一條一條插入                students.add(student);            }            studentService.saveBatch(students);            sqlSession.commit();            stopWatch.stop();            System.out.println("mybatis plus save batch:" + stopWatch.getTotalTimeMillis());        } finally {            sqlSession.close();        }    }

發(fā)現(xiàn)花費9204毫秒,比一條條插入數(shù)據(jù)性能提高十幾倍wO528資訊網(wǎng)——每日最新資訊28at.com

圖片wO528資訊網(wǎng)——每日最新資訊28at.com

3.手動拼接 SQL:挑戰(zhàn)傳統(tǒng)的方式wO528資訊網(wǎng)——每日最新資訊28at.com

<insert id="saveBatch2">    insert into springboot_mp.tb_student ( stuid, name, age, sex, dept, address)    values    <foreach collection="students" item="stu" index="index" separator=",">          ( #{stu.stuid}, #{stu.name}, #{stu.age}, #{stu.sex}, #{stu.dept}, #{stu.address})    </foreach></insert>

發(fā)現(xiàn)花費10958毫秒,比一條條插入數(shù)據(jù)性能提高十幾倍,但是和saveBatch性能相差不大wO528資訊網(wǎng)——每日最新資訊28at.com

既然都驗證都這了,我就在想,要不要使用JDBC批量插入進行驗證一下,看會不會出現(xiàn)原始的才是最好的結(jié)果wO528資訊網(wǎng)——每日最新資訊28at.com

4.JDBC 的 executeBatch 方法wO528資訊網(wǎng)——每日最新資訊28at.com

嘗試直接使用 JDBC 提供的 executeBatch 方法,看是否有意外的性能提升。wO528資訊網(wǎng)——每日最新資訊28at.com

@Test    public void JDBCSaveBatch() throws SQLException {        SqlSession sqlSession = sqlSessionFactory.openSession();        Connection connection = sqlSession.getConnection();        connection.setAutoCommit(false);        String sql ="insert into springboot_mp.tb_student ( stuid, name, age, sex, dept, address) values (?, ?, ?, ?, ?, ?);";        try (PreparedStatement statement = connection.prepareStatement(sql)) {            List<Student> students = new ArrayList<>();            StopWatch stopWatch = new StopWatch();            stopWatch.start("mybatis plus JDBCSaveBatch");            for (int i = 0; i < 100000; i++) {                statement.setString(1,"6840"+i);                statement.setString(2,"zhangsan"+i);                statement.setInt(3,(i%100));                if(i%2==0){                    statement.setInt(4,0);                }else {                    statement.setInt(4,1);                }                statement.setString(5,"計算機學(xué)院");                statement.setString(6,"廣東省廣州市番禺"+i+"號");                statement.addBatch();            }            statement.executeBatch();            connection.commit();            stopWatch.stop();            System.out.println("mybatis plus JDBCSaveBatch:" + stopWatch.getTotalTimeMillis());        }        catch (Exception e){            System.out.println(e.getMessage());        }        finally {            sqlSession.close();        }

JDBC executeBatch 的性能會好點,耗費6667毫秒wO528資訊網(wǎng)——每日最新資訊28at.com

圖片wO528資訊網(wǎng)——每日最新資訊28at.com

但是感覺到這里以后,覺得時候還是比較長,有沒有可以再進行優(yōu)化的方式,然后我就在ClientPreparedStatement類中發(fā)現(xiàn)有一個叫做rewriteBatchedStatements 的屬性,從名字來看是要重寫批操作的 Statement,前面batchHasPlainStatements 已經(jīng)是 false,取反肯定是 true,所以只要這參數(shù)是 true 就會進行一波操作。rewriteBatchedStatements默認(rèn)是 false。wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

圖片wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

大家也可以自行網(wǎng)上搜索一下這個神奇的屬性然后我在url添加上這個屬性wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

然后繼續(xù)跑了下 mybatis-plus 自帶的 saveBatch,果然性能大大提高直接由原來的9204毫秒,提升到現(xiàn)在的3903毫秒wO528資訊網(wǎng)——每日最新資訊28at.com

圖片圖片wO528資訊網(wǎng)——每日最新資訊28at.com

再來跑一下JDBC 的 executeBatch ,果然也提高了。wO528資訊網(wǎng)——每日最新資訊28at.com

直接由原來的6667毫秒,提升到了3794毫秒wO528資訊網(wǎng)——每日最新資訊28at.com

圖片wO528資訊網(wǎng)——每日最新資訊28at.com

結(jié)果對比

批量保存方式
wO528資訊網(wǎng)——每日最新資訊28at.com

數(shù)據(jù)量(條)
wO528資訊網(wǎng)——每日最新資訊28at.com

耗時(ms)
wO528資訊網(wǎng)——每日最新資訊28at.com

單條循環(huán)插入
wO528資訊網(wǎng)——每日最新資訊28at.com

100000
wO528資訊網(wǎng)——每日最新資訊28at.com

195569
wO528資訊網(wǎng)——每日最新資訊28at.com

mybatis-plus saveBatch
wO528資訊網(wǎng)——每日最新資訊28at.com


wO528資訊網(wǎng)——每日最新資訊28at.com

100000
wO528資訊網(wǎng)——每日最新資訊28at.com

9204
wO528資訊網(wǎng)——每日最新資訊28at.com

mybatis-plus saveBatch(添加 rewrite 參數(shù))
wO528資訊網(wǎng)——每日最新資訊28at.com

100000
wO528資訊網(wǎng)——每日最新資訊28at.com

3903
wO528資訊網(wǎng)——每日最新資訊28at.com

手動拼接 SQL
wO528資訊網(wǎng)——每日最新資訊28at.com

100000
wO528資訊網(wǎng)——每日最新資訊28at.com

6667
wO528資訊網(wǎng)——每日最新資訊28at.com

JDBC executeBatch
wO528資訊網(wǎng)——每日最新資訊28at.com

100000
wO528資訊網(wǎng)——每日最新資訊28at.com

10958
wO528資訊網(wǎng)——每日最新資訊28at.com

JDBC executeBatch(添加 rewrite 參數(shù))
wO528資訊網(wǎng)——每日最新資訊28at.com

100000
wO528資訊網(wǎng)——每日最新資訊28at.com

3794
wO528資訊網(wǎng)——每日最新資訊28at.com

結(jié)論

通過實驗結(jié)果,我們可以得出以下結(jié)論:wO528資訊網(wǎng)——每日最新資訊28at.com

  • mybatis-plus 的 saveBatch 方法相比單條循環(huán)插入在性能上有所提升,但仍然不夠理想。
  • JDBC 的 executeBatch 方法在默認(rèn)情況下性能與 mybatis-plus 的 saveBatch 類似,但通過設(shè)置 rewriteBatchedStatements 參數(shù)為 true 可顯著提高性能。
  • rewriteBatchedStatements 參數(shù)的作用是將一批插入拼接成 insert into xxx values (a),(b),(c)... 這樣的一條語句形式,提高了性能。

優(yōu)化建議

如果您在項目中需要進行批量插入操作,我建議考慮以下優(yōu)化方案:wO528資訊網(wǎng)——每日最新資訊28at.com

  • 如果使用 mybatis-plus,可以嘗試將 JDBC 連接字符串中的 rewriteBatchedStatements 參數(shù)設(shè)置為 true,以提高 saveBatch 方法的性能。

本文鏈接:http://www.www897cc.com/showinfo-26-55086-0.htmlMyBatis批量插入數(shù)據(jù)優(yōu)化,那叫一個優(yōu)雅!

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: C++中的內(nèi)存管理:深入理解與應(yīng)用

下一篇: Go語言中的性能考慮和優(yōu)化

標(biāo)簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 德清县| 石嘴山市| 沙田区| 民县| 静乐县| 天津市| 晋江市| 岢岚县| 江津市| 绥滨县| 商南县| 朝阳市| 盐山县| 天津市| 漳浦县| 巴青县| 定襄县| 烟台市| 青神县| 新兴县| 门头沟区| 南靖县| 衢州市| 丹江口市| 北海市| 黎平县| 九寨沟县| 大姚县| 南江县| 镇平县| 邹平县| 盐城市| 介休市| 和林格尔县| 临邑县| 普兰县| 苏州市| 本溪| 永安市| 乌兰县| 太康县|