最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mybatis-Plus多種批量插入方案對比小結(jié)

 更新時間:2024年10月31日 10:36:49   作者:北i  
在項目中優(yōu)化Mybatis-Plus批量插入性能是關(guān)鍵,通過比較不同方案,本文就來介紹一下Mybatis-Plus多種批量插入方案對比小結(jié),感興趣都的可以了解一下

背景

六月某日上線了一個日報表任務(wù),因是第一次上線,故需要為歷史所有日期都初始化一次報表數(shù)據(jù)
在執(zhí)行過程中發(fā)現(xiàn)新增特別的慢:插入十萬條左右的數(shù)據(jù),SQL執(zhí)行耗費高達三分多鐘

因很早就聽聞過mybatis-plus的[偽]批量新增的問題,很快鎖定問題并進行修復(fù),下面細節(jié)描述多種批量新增方案的具體性能表現(xiàn)

# 測試表結(jié)構(gòu)
DROP TABLE IF EXISTS `biz_batch_insert_test`;
CREATE TABLE `biz_batch_insert_test` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(600) DEFAULT NULL,
  `age` tinyint(4) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

# name字段給的長度大了些,模擬生產(chǎn)實際表結(jié)構(gòu)占用
# 測試庫版本:5.7.5

方案一:傳統(tǒng)for循環(huán)

@Test
public void testUserInsert() {
    long l = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++) {
        TestUser testUser = new TestUser();
        testUser.setName("中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國");
        testUser.setAge(20);
        testUserService.save(testUser);
    }
    System.out.println("毫秒==>" + (System.currentTimeMillis() - l));
}

# 插入10萬條耗時:238040ms,大約4分鐘

方案二:使用Mybatis-Plus的saveBatch

@Test
public void testUserInsert() {
    long l = System.currentTimeMillis();
    List<TestUser> list = new ArrayList<>();
    for (int i = 0; i < 100000; i++) {
        TestUser testUser = new TestUser();
        testUser.setName("中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國");
        testUser.setAge(20);
        list.add(testUser);
    }
    testUserService.saveBatch(list);
    System.out.println("毫秒==>" + (System.currentTimeMillis() - l));
}

# 插入耗時:62180ms,大約1分鐘

這里先留下一張saveBatch的SQL日志截圖,這里的日志是一個insert into語句,下面帶了一千條數(shù)據(jù)(MP默認一千條一個批次),使用Mybatis Log插件查看還是單條的SQL

方案三:在方案二的基礎(chǔ)上修改MySQL連接參數(shù):rewriteBatchedStatements=true

# 與方案二測試代碼相同
# 插入耗時:35260ms,大約半分鐘

其SQL日志也如上方案二所示,MySQL Jdbc驅(qū)動在默認情況下會無視executeBatch()語句,把我們期望批量執(zhí)行的一組sql語句拆散,一條一條地發(fā)給MySQL數(shù)據(jù)庫,直接造成較低的性能
Mysql連接配置鏈接

方案四:使用Mybatis-Plus提供的擴展插件:InsertBatchSomeColumn

@Test
public void testUserInsert() {
    long l = System.currentTimeMillis();
    List<TestUser> list = new ArrayList<>();
    for (int i = 0; i < 10000; i++) {
        TestUser testUser = new TestUser();
        testUser.setName("中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國中國");
        testUser.setAge(20);
        list.add(testUser);
        // 因為mysql的參數(shù)max_allowed_packet限制,所以這里程序改成單批1000條
        if(list.size() == 1000){
            testUserMapper.insertBatchSomeColumn(list);
            list.clear();
        }
    }
    System.out.println("毫秒==>" + (System.currentTimeMillis() - l));
}

# 插入耗時:24410ms,大約24秒

再來看看此時控制臺的SQL,與方案二的SQL有著明顯的區(qū)別,這里是將批次插入的數(shù)據(jù)拼接在同一條SQL中,對于MySQL處理來說,這是真的批量新增

配置方式

// 1. 自定義SQL注入器
public class BatchSaveSqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        // 注意:保留mybatis-plus的自帶方法
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        return methodList;
    }
}

// 2. 實現(xiàn)自定義baseMapper
public interface BatchSaveBaseMapper<T> extends BaseMapper<T> {
    /**
     * 批量插入 僅適用于mysql
     *
     * @param entityList
     *            實體列表
     * @return 影響行數(shù)
     */
    Integer insertBatchSomeColumn(Collection<T> entityList);
}



// 3. 注入插件
// 方式一
@Configuration
public class MybatisPlusConfig {
    /**
     * 分頁插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
    /**
     * SQL注入器
     */
    @Bean
    public BatchSaveSqlInjector easySqlInjector() {
        return new BatchSaveSqlInjector();
    }
}

// 方式二
// 若項目有自定義SqlSessionFactory,也可在初始化時將自定義SQL注入器植入,參考下圖MybatisPlusAutoConfiguration.sqlSessionFactory的做法

總結(jié)

插入10萬數(shù)據(jù)耗時(秒)
mybatis-plus:save238
mybatis-plus的saveBatch:rewriteBatchedStatements=false62
mybatis-plus的saveBatch:rewriteBatchedStatements=true35
mybatis-plus擴展插件:InsertBatchSomeColumn24

到此這篇關(guān)于Mybatis-Plus多種批量插入方案對比小結(jié)的文章就介紹到這了,更多相關(guān)Mybatis-Plus多種批量插入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Windows系統(tǒng)下Eclipse搭建ESP32編譯環(huán)境及安裝過程

    Windows系統(tǒng)下Eclipse搭建ESP32編譯環(huán)境及安裝過程

    Ecppse 使用了 ESP-IDF 中的 Makefile 支持。這意味著您需要從創(chuàng)建 ESP-IDF 項目開始。您可以使用 github 中的 idf-template 項目,接下來通過本文給大家介紹Windows系統(tǒng)下Eclipse搭建ESP32編譯環(huán)境及安裝過程,感興趣的朋友一起看看吧
    2021-10-10
  • spring boot 下支付寶的開箱既用環(huán)境

    spring boot 下支付寶的開箱既用環(huán)境

    這篇文章主要介紹了spring boot 下支付寶的開箱既用環(huán)境包括使用場景和使用技巧,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-10-10
  • Java基礎(chǔ)入門總結(jié)之序列化和反序列化

    Java基礎(chǔ)入門總結(jié)之序列化和反序列化

    序列化是一種對象持久化的手段,普遍應(yīng)用在網(wǎng)絡(luò)傳輸、RMI等場景中,下面這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)入門總結(jié)之序列化和反序列化的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • jdk源碼閱讀Collection詳解

    jdk源碼閱讀Collection詳解

    這篇文章主要介紹了jdk源碼閱讀Collection詳解,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • SpringBoot整合RabbitMQ實戰(zhàn)教程附死信交換機

    SpringBoot整合RabbitMQ實戰(zhàn)教程附死信交換機

    這篇文章主要介紹了SpringBoot整合RabbitMQ實戰(zhàn)附加死信交換機,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • Spring IOC源碼剖析_如何整體認知Spring體系結(jié)構(gòu)

    Spring IOC源碼剖析_如何整體認知Spring體系結(jié)構(gòu)

    這篇文章主要介紹了Spring IOC源碼剖析_如何整體認知Spring體系結(jié)構(gòu)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Springboot 項目一啟動就獲取HttpSession的兩種方法

    Springboot 項目一啟動就獲取HttpSession的兩種方法

    在SpringBoot項目中,HttpSession是有狀態(tài)的,通常只有在用戶發(fā)起 HTTP請求并建立會話后才會創(chuàng)建,因此,在項目啟動時是無法獲取到 HttpSession,下面就來介紹一下Springboot啟動就獲取HttpSession,感興趣的可以了解一下
    2025-10-10
  • Spring為IOC容器注入Bean的五種方式詳解

    Spring為IOC容器注入Bean的五種方式詳解

    這篇文章主要介紹了Spring為IOC容器注入Bean的五種方式詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • springboot jta atomikos實現(xiàn)分布式事物管理

    springboot jta atomikos實現(xiàn)分布式事物管理

    這篇文章主要介紹了springboot jta atomikos實現(xiàn)分布式事物管理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • SpringBoot詳細講解如何創(chuàng)建及刷新Spring容器bean

    SpringBoot詳細講解如何創(chuàng)建及刷新Spring容器bean

    前面看spring源碼時可以發(fā)現(xiàn)refresh()方法十分重要。在這個方法中會加載beanDefinition,同時創(chuàng)建bean對象。那么在springboot中有沒有使用這個refresh()方法呢
    2022-06-06

最新評論

闽侯县| 辽宁省| 肇庆市| 怀远县| 东港市| 凤翔县| 凤山县| 夹江县| 理塘县| 巩义市| 金堂县| 驻马店市| 景洪市| 新竹市| 金平| 潼关县| 南江县| 平邑县| 余姚市| 克什克腾旗| 抚顺县| 师宗县| 南通市| 上虞市| 容城县| 上蔡县| 鹤岗市| 瑞丽市| 虹口区| 马龙县| 江西省| 裕民县| 溆浦县| 德令哈市| 龙南县| 山东| 淮滨县| 昆明市| 肃南| 兴和县| 浮梁县|