国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Mybatis批量插入/更新性能優(yōu)化思路

這篇具有很好參考價值的文章主要介紹了Mybatis批量插入/更新性能優(yōu)化思路。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

????????最近在做數(shù)據(jù)寫入服務(wù)的性能優(yōu)化,主要是基于Mybatis-Plus實現(xiàn)一套批量寫數(shù)據(jù)的服務(wù),不過該服務(wù)是支持整個平臺所有需要持久化的業(yè)務(wù)實體。所以這種服務(wù)不僅僅有insert操作還有update的操作。根據(jù)以往的MySQL數(shù)據(jù)庫寫入經(jīng)驗,主要總結(jié)了兩套批量插入、批量插入更新的優(yōu)化思路。

應(yīng)用場景

1、純插入、純更新

2、插入+更新共存

可行性分析

在本地環(huán)境使用JMeter驗證MySQL插入性能,以t_xxx表(55個字段)表為例,分別用1個線程、2個線程、10個線程測試寫入Mysql,不同批次大小批量Replace into結(jié)果如下:

批次大小

線程數(shù)

TPS

10/20/50/100/200/500

1/2/10

空表replace into(全是insert)

50w數(shù)據(jù)表replace into(全是update)

10

1

125*10=1250

99*10=990

20

106*20=2120

76*20=1520

50

70*50=3500

40*50=2000

100

42*100=4200

22*100=2200

200

12*200=2400

10*200=2000

500

3.6*500=1800

1.2*500=600

10

2

?

210*10=2100

190*10=1900

20

186*20=3820

138*20=2760

50

128*50=6400

74*50=3700

100

73*100=7300

42*100=4200

200

22*200=4400

20*200=4000

500

6.7*500=3350

6.1*500=3050

10

10

?

1200*10=12000

641*10=6410

20

905*20=18100

429*20=8580

50

525*50=26250

192*50=9600

100

230*100=23000

85*100=8500

200

110*200=22000

42*200=8400

500

25*500=12500

16*500=8000

  • 無論空表insert、50w表update,最優(yōu)的批次都是在50~100,所以最大500一個批次寫庫是否合理?
  • 50w表單線程插入Replace寫入TPS=2000~4200

思路

主要從兩個方面來考慮這個問題:

  1. SQL本身的執(zhí)行效率
  2. 網(wǎng)絡(luò)I/O

純插入、純更新

批量插入的時候,一般有兩種思路:

(1)用一個 for 循環(huán),把數(shù)據(jù)一條一條的插入(這種需要開啟批處理)

insert into t_xx(a) values(1);
insert into t_xx(a) values(2);

開啟批處理簡單的講就是openSession的時候帶上參數(shù)ExecutorType.BATCH,可以幾乎無損優(yōu)化你的代碼性能。

SqlSession session = sessionFactory.openSession(ExecutorType.BATCH);

(2)生成一條插入 sql,類似這種

insert into t_xx(a) values(1),(2);
  • 這種方案的優(yōu)勢在于只有一次網(wǎng)絡(luò) IO,即使分片處理也只是數(shù)次網(wǎng)絡(luò) IO,所以這種方案不會在網(wǎng)絡(luò) IO 上花費太多時間。
  • 當(dāng)然這種方案有好幾個劣勢,一是 SQL 太長了,甚至可能需要分片后批量處理;二是無法充分發(fā)揮 PreparedStatement 預(yù)編譯的優(yōu)勢,SQL 要重新解析且無法復(fù)用;三是最終生成的 SQL 如果太長了,數(shù)據(jù)庫管理器解析這么長的 SQL 也需要時間。

插入+更新共存

批量插入和更新,一般采用

(1)insert、update語句分開批量處理

第一種這種和上述純插入、純更新處理類似,但是一般這種處理比較麻煩的點在于如何分類。一般對于區(qū)分可能需要根據(jù)UK查詢一把。

(2)使用replace into語句批量處理

replace into t_xx(a) values(1),(2);

????????這種方案主要的原理是delete + insert,這種如果在多線程下執(zhí)行出現(xiàn)死鎖的概率很大。

目前基于mybatis-plus自定義SQL注入器方法實現(xiàn),主要代碼如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-857907.html

@Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = new NoKeyGenerator();
        String scriptSql = "<script>\n%s\nVALUES %s\n</script>";
        String replaceSql = "REPLACE INTO %s %s";
        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(false) +
            this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);
        String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET;
        String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(ENTITY_DOT, false) +
            this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY);
        insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;
        String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA);

        String keyProperty = null;
        String keyColumn = null;
        if (tableInfo.havePK()) {
            if (tableInfo.getIdType() == IdType.AUTO) {
                keyGenerator = new NoKeyGenerator();
                keyProperty = tableInfo.getKeyProperty();
                keyColumn = tableInfo.getKeyColumn();
            } else {
                if (null != tableInfo.getKeySequence()) {
                    keyGenerator = TableInfoHelper.genKeyGenerator(functionName, tableInfo, builderAssistant);
                    keyProperty = tableInfo.getKeyProperty();
                    keyColumn = tableInfo.getKeyColumn();
                }
            }
        }
        String sql = String.format(scriptSql, String.format(replaceSql, tableInfo.getTableName(), columnScript), valuesScript);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, functionName, sqlSource, keyGenerator, keyProperty, keyColumn);
    }

(3)使用insert into tb values() on duplicate key update批量處理

insert into t_xx(a) values(1),(2) on duplicate key update a=values(a)

? ? ? ? 這種方案主要的原理是根據(jù)uk是否沖突判斷,是否執(zhí)行insert或者update,這種如果在多線程下執(zhí)行會出現(xiàn)死鎖,但是沖突概率相比較方案2要小很多。

目前基于mybatis-plus自定義SQL注入器方法實現(xiàn),主要代碼如下:

@Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = new NoKeyGenerator();
        String scriptSql = "<script>\n%s\nVALUES %s on duplicate key update %s\n</script>";
        String insertSql = "INSERT INTO %s %s";
        String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(false) +
            this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);
        String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET;
        String updateSqlColumn = getUpdateSqlProperties(insertSqlColumn);
        String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(ENTITY_DOT, false) +
            this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY);
        insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;
        String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA);

        String keyProperty = null;
        String keyColumn = null;
        if (tableInfo.havePK()) {
            if (tableInfo.getIdType() == IdType.AUTO) {
                keyGenerator = new NoKeyGenerator();
                keyProperty = tableInfo.getKeyProperty();
                keyColumn = tableInfo.getKeyColumn();
            } else {
                if (null != tableInfo.getKeySequence()) {
                    keyGenerator = TableInfoHelper.genKeyGenerator(functionName, tableInfo, builderAssistant);
                    keyProperty = tableInfo.getKeyProperty();
                    keyColumn = tableInfo.getKeyColumn();
                }
            }
        }
        String sql = String.format(scriptSql, String.format(insertSql, tableInfo.getTableName(), columnScript), valuesScript, updateSqlColumn);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, functionName, sqlSource, keyGenerator, keyProperty, keyColumn);
    }

到了這里,關(guān)于Mybatis批量插入/更新性能優(yōu)化思路的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Mybatis批量更新數(shù)據(jù)及其優(yōu)化

    需求場景 :定時任務(wù)中,從其他平臺同步數(shù)據(jù),并更新當(dāng)前平臺數(shù)據(jù)庫,表數(shù)據(jù)3W+,分批更新某個字段,耗時巨大,約30min,嘗試性能優(yōu)化。 批量更新的幾種常見方式: 1.foreach 循環(huán) 在mybatis的xml文件中,使用foreach動態(tài)標(biāo)簽拼接SQL語句,每一條數(shù)據(jù)的更新語句對應(yīng)一條update語

    2024年02月10日
    瀏覽(19)
  • Mybatis批量插入、修改

    ? ? ? ? 在 MyBatis 中, foreach 標(biāo)簽用于遍歷集合類型的條件,并且可以將多個參數(shù)值拼接成為 SQL 語句的一個部分,通常被用于批量插入或更新等操作。? foreach屬性及介紹 ? ? ? ?? 屬性 介紹 collection 集合名稱 item 字符別名 index 索引別名 open 循環(huán)前綴 close 循環(huán)后綴 separato

    2024年02月07日
    瀏覽(18)
  • Mybatis批量插入

    使用Mybatis框架批量插入的3種方法:多次調(diào)用insert方法、foreach標(biāo)簽、batch模式 后端java代碼:

    2024年02月12日
    瀏覽(18)
  • Mybatis批量插入方式有哪些

    MyBatis批量插入有多種寫法,最后博主總結(jié)一些常見的批量插入寫法供大家參考 使用XML配置文件進(jìn)行批量插入:在XML映射文件中使用 insert 標(biāo)簽,并通過 foreach 標(biāo)簽迭代批量數(shù)據(jù),然后在SQL語句中使用 VALUES 。 使用Java注解進(jìn)行批量插入:在實體類上使用 @Insert 注解,并

    2024年02月11日
    瀏覽(20)
  • MyBatis的五種批量插入

    MyBatis的五種批量插入

    一.直接循環(huán)插入 最終耗時:14s多 二.關(guān)閉MySql自動提交,手動進(jìn)行循環(huán)插入提交 平均:0.12s 第三種:用List集合的方式插入數(shù)據(jù)庫(推薦) 第四種: MyBatis-Plus提供的SaveBatch方法 直接報錯: 看報錯信息: 長串:Servlet.service() for servlet [dispatcherServlet] in context with path [] threw excep

    2024年03月15日
    瀏覽(17)
  • mybatis-plus 批量插入示例

    mybatis-plus 批量插入示例

    正常我們使用mybatis-plus插入的時候,首先想到的是??saveBatch?方法,不過看了下打印出來的sql和底層代碼,才發(fā)現(xiàn)它并不是真正的批量插入。 ? ? 實現(xiàn)層? ?ServiceImpl?中的代碼為 通過監(jiān)控控制臺發(fā)現(xiàn),它只是循環(huán)每1000條去插入,效率非常低。 ? 參考網(wǎng)友的文章,找到一個支

    2024年02月15日
    瀏覽(23)
  • MyBatis 批量插入數(shù)據(jù)的 3 種方法!

    MyBatis 批量插入數(shù)據(jù)的 3 種方法!

    數(shù)據(jù)庫的最終效果如下: 接下來我們將使用 Spring Boot 項目,批量插入 10W 條數(shù)據(jù)來分別測試各個方法的執(zhí)行時間。? 循環(huán)單次插入的(測試)核心代碼如下: 運行以上程序,花費了 88574 毫秒,如下圖所示: MP 批量插入功能核心實現(xiàn)類有三個:UserController(控制器)、UserS

    2024年02月07日
    瀏覽(21)
  • Mybatis-plus---的批量插入

    Mybatis-plus---的批量插入

    批量插入 一、繼承IService(偽批量) 二、insertBatchSomeColumn Mybatis-plus很強(qiáng),為我們誕生了極簡CURD操作,但對于數(shù)據(jù)批量操作,顯然默認(rèn)提供的insert方法是不夠看的了,于是它和它來了!!! Mybatis-plus提供的兩種插入方式 ?????? ??繼承IService(偽批量) ????????insertBatchSo

    2024年02月16日
    瀏覽(21)
  • SpringBoot+MyBatis批量插入數(shù)據(jù)的三種方式

    最近導(dǎo)入表格數(shù)據(jù)時需要同時插入修改大量數(shù)據(jù),研究了一下有三種實現(xiàn)方式 1、用for循環(huán)調(diào)用sql插入數(shù)據(jù) 這種方式插入大量數(shù)據(jù)時,效率非常底下,不推薦 2、利用mybatis的foreach來實現(xiàn)循環(huán)插入 這種方式插入大量數(shù)據(jù)時,好處是不用頻繁訪問數(shù)據(jù)庫,一條sql搞定,效率比較

    2024年02月16日
    瀏覽(19)
  • MyBatis-plus的批量插入方式對比分析

    ??【摘要】Mybatis批量插入一直是開發(fā)者重點關(guān)注的問題,本文列舉了Mybatis的五種插入方式進(jìn)行對比分析,驗證了五種批量插入的方式的優(yōu)先級。 ??略。 1、編寫UserService服務(wù)類,測試一萬條數(shù)據(jù)的耗時情況: 2、編寫UserMapper接口 3、編寫UserMapper.xml文件 4、進(jìn)行單元測試

    2024年02月07日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包