欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

背景

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

因很早就聽聞過mybatis-plus的[偽]批量新增的問題,很快鎖定問題并進行修復,下面細節(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)文章

  • java線程池ExecutorService超時處理小結(jié)

    java線程池ExecutorService超時處理小結(jié)

    使用ExecutorService時,設置子線程執(zhí)行超時是一個常見需求,本文就來詳細的介紹一下ExecutorService超時的三種方法,感興趣的可以了解一下
    2024-09-09
  • 基于Transactional事務的使用以及注意說明

    基于Transactional事務的使用以及注意說明

    這篇文章主要介紹了Transactional事務的使用以及注意說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 詳解Java線程池的使用(7種創(chuàng)建方法)

    詳解Java線程池的使用(7種創(chuàng)建方法)

    這篇文章主要介紹了詳解Java線程池的使用(7種創(chuàng)建方法),線程池的創(chuàng)建?式總共包含7種,其中6種是通過Executors創(chuàng)建的,1種是通過ThreadPoolExecutor創(chuàng)建的,今天我們就來詳細說一下
    2023-03-03
  • Java停止線程的3種方法

    Java停止線程的3種方法

    這篇文章主要分享Java停止線程的3種方法,分別是自定義中斷標識符,停止線程、使用線程中斷方法interrupt停止線程、使用stop停止線程。下文詳細介紹需要的小伙伴可以參考一下
    2022-05-05
  • java實現(xiàn)簡單發(fā)送郵件功能

    java實現(xiàn)簡單發(fā)送郵件功能

    這篇文章主要為大家詳細介紹了java實現(xiàn)簡單發(fā)送郵件功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Spring Boot中整合Spring Security并自定義驗證代碼實例

    Spring Boot中整合Spring Security并自定義驗證代碼實例

    本篇文章主要介紹了Spring Boot中整合Spring Security并自定義驗證代碼實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Java?SE判斷兩個文件內(nèi)容是否相同的多種方法代碼

    Java?SE判斷兩個文件內(nèi)容是否相同的多種方法代碼

    昨天因為要幫師兄的忙所以看了一下如何判斷兩個文件內(nèi)容是否相同,這里給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于Java?SE判斷兩個文件內(nèi)容是否相同的多種方法,需要的朋友可以參考下
    2023-11-11
  • maven環(huán)境變量配置以及失敗原因解析

    maven環(huán)境變量配置以及失敗原因解析

    這篇文章主要為大家詳細介紹了maven環(huán)境變量配置教程,以及為大家解析了安裝失敗的原因,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • Springboot集成規(guī)則引擎Drools方式

    Springboot集成規(guī)則引擎Drools方式

    這篇文章主要介紹了Springboot集成規(guī)則引擎Drools方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • java實現(xiàn)用戶自動登錄

    java實現(xiàn)用戶自動登錄

    這篇文章主要為大家詳細介紹了java用戶自動登錄的實現(xiàn)方法,分為六個步驟實現(xiàn)用戶自動登錄,并驗證用戶是否已經(jīng)登錄,感興趣的小伙伴們可以參考一下
    2016-03-03

最新評論