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

當前位置:首頁 > 科技  > 軟件

MyBatis批量插入數據優化,那叫一個優雅!

來源: 責編: 時間:2024-01-02 09:30:34 202觀看
導讀在項目開發中,我們經常需要進行大量數據的批量插入操作。然而,在實際應用中,插入大量數據時性能常常成為一個瓶頸。在我最近的項目中,我發現了一些能夠顯著提升批量插入性能的方法,并進行了一系列實驗來驗證它們的有效性。

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

今日內容介紹,大約花費15分鐘CER28資訊網——每日最新資訊28at.com

圖片圖片CER28資訊網——每日最新資訊28at.com

背景介紹

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

圖片圖片CER28資訊網——每日最新資訊28at.com

這是因為最終在執行的時候還是通過for循環一條條執行insert,然后再一批的進行flush ,默認批的消息為1000CER28資訊網——每日最新資訊28at.com

圖片圖片CER28資訊網——每日最新資訊28at.com

為了找到更優秀的解決方案,我展開了一場性能優化的探索之旅。好了我們現在開始探索CER28資訊網——每日最新資訊28at.com

實驗準備

  • 創建一張表tb_student
create table springboot_mp.tb_student(    id      bigint auto_increment comment '主鍵ID'        primary key,    stuid   varchar(40)   not null comment '學號',    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));
  • 創建spring-boot-mybatis-demo項目并在pom.xml中添加依賴

圖片圖片CER28資訊網——每日最新資訊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 #指定服務名  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生成代碼

圖片圖片CER28資訊網——每日最新資訊28at.com

圖片圖片CER28資訊網——每日最新資訊28at.com

圖片圖片CER28資訊網——每日最新資訊28at.com

探索實驗

每次都是插入100000條數據CER28資訊網——每日最新資訊28at.com

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

  1. 單條循環插入:傳統方法的基準

首先,我采用了傳統的單條循環插入方法,將每條數據逐一插入數據庫,作為性能對比的基準。CER28資訊網——每日最新資訊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("計算機學院");                student.setAddress("廣東省廣州市番禺"+i+"號");                //一條一條插入                studentService.save(student);            }            sqlSession.commit();            stopWatch.stop();            System.out.println("mybatis plus save one:" + stopWatch.getTotalTimeMillis());        } finally {            sqlSession.close();        }    }}

發現花費了195569毫秒CER28資訊網——每日最新資訊28at.com

圖片圖片CER28資訊網——每日最新資訊28at.com

  1. mybatis-plus 的 saveBatch 方法

現在嘗試 mybatis-plus 提供的 saveBatch 方法,期望它能夠提高性能。CER28資訊網——每日最新資訊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("計算機學院");                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();        }    }

發現花費9204毫秒,比一條條插入數據性能提高十幾倍CER28資訊網——每日最新資訊28at.com

圖片CER28資訊網——每日最新資訊28at.com

3.手動拼接 SQL:挑戰傳統的方式CER28資訊網——每日最新資訊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>

發現花費10958毫秒,比一條條插入數據性能提高十幾倍,但是和saveBatch性能相差不大CER28資訊網——每日最新資訊28at.com

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

4.JDBC 的 executeBatch 方法CER28資訊網——每日最新資訊28at.com

嘗試直接使用 JDBC 提供的 executeBatch 方法,看是否有意外的性能提升。CER28資訊網——每日最新資訊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,"計算機學院");                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毫秒CER28資訊網——每日最新資訊28at.com

圖片CER28資訊網——每日最新資訊28at.com

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

圖片圖片CER28資訊網——每日最新資訊28at.com

圖片CER28資訊網——每日最新資訊28at.com

圖片圖片CER28資訊網——每日最新資訊28at.com

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

圖片圖片CER28資訊網——每日最新資訊28at.com

然后繼續跑了下 mybatis-plus 自帶的 saveBatch,果然性能大大提高直接由原來的9204毫秒,提升到現在的3903毫秒CER28資訊網——每日最新資訊28at.com

圖片圖片CER28資訊網——每日最新資訊28at.com

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

直接由原來的6667毫秒,提升到了3794毫秒CER28資訊網——每日最新資訊28at.com

圖片CER28資訊網——每日最新資訊28at.com

結果對比

批量保存方式
CER28資訊網——每日最新資訊28at.com

數據量(條)
CER28資訊網——每日最新資訊28at.com

耗時(ms)
CER28資訊網——每日最新資訊28at.com

單條循環插入
CER28資訊網——每日最新資訊28at.com

100000
CER28資訊網——每日最新資訊28at.com

195569
CER28資訊網——每日最新資訊28at.com

mybatis-plus saveBatch
CER28資訊網——每日最新資訊28at.com


CER28資訊網——每日最新資訊28at.com

100000
CER28資訊網——每日最新資訊28at.com

9204
CER28資訊網——每日最新資訊28at.com

mybatis-plus saveBatch(添加 rewrite 參數)
CER28資訊網——每日最新資訊28at.com

100000
CER28資訊網——每日最新資訊28at.com

3903
CER28資訊網——每日最新資訊28at.com

手動拼接 SQL
CER28資訊網——每日最新資訊28at.com

100000
CER28資訊網——每日最新資訊28at.com

6667
CER28資訊網——每日最新資訊28at.com

JDBC executeBatch
CER28資訊網——每日最新資訊28at.com

100000
CER28資訊網——每日最新資訊28at.com

10958
CER28資訊網——每日最新資訊28at.com

JDBC executeBatch(添加 rewrite 參數)
CER28資訊網——每日最新資訊28at.com

100000
CER28資訊網——每日最新資訊28at.com

3794
CER28資訊網——每日最新資訊28at.com

結論

通過實驗結果,我們可以得出以下結論:CER28資訊網——每日最新資訊28at.com

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

優化建議

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

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

本文鏈接:http://www.www897cc.com/showinfo-26-55101-0.htmlMyBatis批量插入數據優化,那叫一個優雅!

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

上一篇: Vue 新一代開發者工具正式開源!

下一篇: Go語言中的性能考慮和優化

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 英山县| 娄烦县| 德昌县| 阿坝县| 内丘县| 永济市| 巩义市| 合山市| 盱眙县| 凭祥市| 黄梅县| 新邵县| 清苑县| 惠来县| 云龙县| 通州区| 阳曲县| 神农架林区| 武义县| 炉霍县| 鸡西市| 肃南| 文成县| 滕州市| 岳普湖县| 娱乐| 大丰市| 大新县| 延津县| 交口县| 攀枝花市| 石屏县| 登封市| 通辽市| 苏尼特右旗| 九寨沟县| 龙游县| 秦皇岛市| 喜德县| 安义县| 冕宁县|