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

Mybatis?大數(shù)據(jù)量批量寫(xiě)優(yōu)化的案例詳解

 更新時(shí)間:2023年05月01日 09:00:09   作者:遇見(jiàn)的昨天  
這篇文章主要介紹了Mybatis?大數(shù)據(jù)量批量寫(xiě)優(yōu)化的示例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

Mybatis 大數(shù)據(jù)量批量寫(xiě)優(yōu)化

在項(xiàng)目中使用批量數(shù)據(jù)插入,經(jīng)常會(huì)用到 mybatis的 foreach,如下:

<insert id="batchInsert" parameterType="java.util.List">
    insert into USER (id, name) values
    <foreach collection="list" item="model" index="index" separator=","> 
        (#{model.id}, #{model.name})
    </foreach>
</insert>

就是將

INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");

轉(zhuǎn)換成

INSERT INTO `table1` (`field1`, `field2`) 
VALUES ("data1", "data2"),
("data1", "data2"),
("data1", "data2"),
("data1", "data2"),
("data1", "data2");

從理論上將,復(fù)用conn,將多次io,轉(zhuǎn)換成一次io,應(yīng)該是提升效率的。但是實(shí)際上當(dāng)數(shù)據(jù)量比較大的時(shí)候,用foreach效率非常低,速度非常慢

當(dāng)表的列數(shù)較多(20+),以及一次性插入的行數(shù)較多(5000+)時(shí),整個(gè)插入的耗時(shí)十分漫長(zhǎng),達(dá)到了14分鐘,這是不能忍的

那為什么使用使用foreach效率如此之低呢??

Mybatis默認(rèn)執(zhí)行器類(lèi)型為Simple,默認(rèn)會(huì)為每一個(gè)sql產(chǎn)生一個(gè)PrepareStatement,而且對(duì)于foreach無(wú)法使用緩存。如果字段和行數(shù)非常多,那么sql必然也會(huì)很長(zhǎng),占位符也會(huì)非常多,除此之外還要建立占位符和參數(shù)之間的映射,那么解析時(shí)間必然會(huì)長(zhǎng)。因此如果values行數(shù)越多,那么解析時(shí)間必然很長(zhǎng)。執(zhí)行效率低。

在這里插入圖片描述


如果非要使用 foreach 的方式來(lái)進(jìn)行批量插入的話,可以考慮減少一條 insert 語(yǔ)句中 values 的個(gè)數(shù),最好能達(dá)到上面曲線的最底部的值,使速度最快。一般按經(jīng)驗(yàn)來(lái)說(shuō),一次性插20~50行數(shù)量是比較合適的,時(shí)間消耗也能接受。

那么如果要用批量插入,改如何優(yōu)化呢?

SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
    SimpleTableMapper mapper = session.getMapper(SimpleTableMapper.class);
    List<SimpleTableRecord> records = getRecordsToInsert(); // not shown
    BatchInsert<SimpleTableRecord> batchInsert = insert(records)
            .into(simpleTable)
            .map(id).toProperty("id")
            .map(firstName).toProperty("firstName")
            .map(lastName).toProperty("lastName")
            .map(birthDate).toProperty("birthDate")
            .map(employed).toProperty("employed")
            .map(occupation).toProperty("occupation")
            .build()
            .render(RenderingStrategy.MYBATIS3);
    batchInsert.insertStatements().stream().forEach(mapper::insert);
    session.commit();
} finally {
    session.close();
}

基本思想是將 MyBatis session 的 executor type 設(shè)為 Batch ,然后通過(guò)遍歷多次執(zhí)行插入語(yǔ)句

就類(lèi)似于JDBC的下面語(yǔ)句一樣。

Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useUnicode=true&characterEncoding=UTF-8&useServerPrepStmts=false&rewriteBatchedStatements=true","root","root");
connection.setAutoCommit(false);
PreparedStatement ps = connection.prepareStatement(
        "insert into tb_user (name) values(?)");
for (int i = 0; i < stuNum; i++) {
    ps.setString(1,name);
    ps.addBatch();
}
ps.executeBatch();
connection.commit();
connection.close();

附錄:Mybatis批量處理優(yōu)化

Mybatis內(nèi)置的ExecutorType有3種,默認(rèn)的是simple單句模式,該模式下它為每個(gè)語(yǔ)句的執(zhí)行創(chuàng)建一個(gè)新的預(yù)處理語(yǔ)句,單句提交sql;batch模式重復(fù)使用已經(jīng)預(yù)處理的語(yǔ)句,并且批量執(zhí)行所有語(yǔ)句,大批量模式下性能更優(yōu)。

請(qǐng)注意batch模式在Insert操作時(shí)事務(wù)沒(méi)有提交之前,是沒(méi)有辦法獲取到自增的id,所以請(qǐng)根據(jù)業(yè)務(wù)情況使用。
使用simple模式提交10000條數(shù)據(jù),時(shí)間為19s,batch模式為6s ,大致情況如此,優(yōu)化的具體還要看提交的語(yǔ)句情況。
如果需要使用 foreach來(lái)優(yōu)化數(shù)據(jù)插入的話,需要將每次插入的記錄控制在 10-100 左右是比較快的,建議每次100來(lái)分割數(shù)據(jù),也就是分而治之思想。

普通插入

默認(rèn)的插入方式是遍歷insert語(yǔ)句,單條執(zhí)行,效率肯定低下,如果成堆插入,更是性能有問(wèn)題。

INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");

foreach 優(yōu)化插入

如果要優(yōu)化插入速度時(shí),可以將許多小型操作組合到一個(gè)大型操作中。理想情況下,這樣可以在單個(gè)連接中一次性發(fā)送許多新行的數(shù)據(jù),并將所有索引更新和一致性檢查延遲到最后才進(jìn)行。

<insert id="batchInsert" parameterType="java.util.List">
    insert into table1 (field1, field2) values
    <foreach collection="list" item="t" index="index" separator=","> 
        (#{t.field1}, #{t.field2})
    </foreach>
</insert>

翻譯成sql語(yǔ)句也就是

INSERT INTO `table1` (`field1`, `field2`) 
VALUES ("data1", "data2"),
("data1", "data2"),
("data1", "data2"),
("data1", "data2"),
("data1", "data2");

到此這篇關(guān)于Mybatis 大數(shù)據(jù)量批量寫(xiě)優(yōu)化的文章就介紹到這了,更多相關(guān)Mybatis 批量寫(xiě)優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 字節(jié)碼調(diào)教入口JVM?寄生插件javaagent

    字節(jié)碼調(diào)教入口JVM?寄生插件javaagent

    這篇文章主要介紹了字節(jié)碼調(diào)教入口JVM?寄生插件javaagent方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Java冒泡排序及優(yōu)化介紹

    Java冒泡排序及優(yōu)化介紹

    大家好,本篇文章主要講的是Java冒泡排序及優(yōu)化介紹,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 深入淺析Java注解框架

    深入淺析Java注解框架

    這篇文章主要介紹了深入淺析Java注解框架的相關(guān)資料,介紹的非常詳細(xì),具有參考價(jià)值,需要的朋友參考下吧
    2016-05-05
  • 零基礎(chǔ)如何系統(tǒng)的學(xué)習(xí)Java

    零基礎(chǔ)如何系統(tǒng)的學(xué)習(xí)Java

    這篇文章主要介紹了零基礎(chǔ)如何系統(tǒng)的學(xué)習(xí)Java,很多朋友糾結(jié)這個(gè)問(wèn)題,教材書(shū)不知道從何學(xué)起,今天小編給大家分享一篇教程幫助到家梳理這方面的知識(shí)
    2020-07-07
  • javaweb中mysql數(shù)據(jù)庫(kù)連接步驟方法及其實(shí)例

    javaweb中mysql數(shù)據(jù)庫(kù)連接步驟方法及其實(shí)例

    這篇文章主要介紹了使用java web 連接MySQL數(shù)據(jù)庫(kù)的驅(qū)動(dòng)方法的相關(guān)知識(shí),本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-04-04
  • Java中TypeReference用法詳情說(shuō)明

    Java中TypeReference用法詳情說(shuō)明

    這篇文章主要介紹了Java中TypeReference用法詳情說(shuō)明,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • Java BufferedWriter BufferedReader 源碼分析

    Java BufferedWriter BufferedReader 源碼分析

    本文是關(guān)于Java BufferedWriter ,BufferedReader 簡(jiǎn)介、分析源碼 對(duì)Java IO 流深入了解,希望看到的同學(xué)對(duì)你有所幫助
    2016-07-07
  • maven 打包時(shí)間戳問(wèn)題

    maven 打包時(shí)間戳問(wèn)題

    這篇文章主要介紹了maven 打包時(shí)間戳問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • Spring?Data?JPA實(shí)現(xiàn)數(shù)據(jù)持久化過(guò)程詳解

    Spring?Data?JPA實(shí)現(xiàn)數(shù)據(jù)持久化過(guò)程詳解

    Spring?Data?JPA是一個(gè)流行的Java持久化框架,它在Java應(yīng)用程序中提供了一種簡(jiǎn)單、一致和易于使用的方式來(lái)訪問(wèn)各種數(shù)據(jù)庫(kù)。本文將介紹Spring?Data?JPA的基本概念和用法并提供一個(gè)完整的實(shí)例,幫助您更好地理解它的使用方法和優(yōu)勢(shì)
    2023-05-05
  • java 多態(tài)實(shí)例代碼

    java 多態(tài)實(shí)例代碼

    這篇文章主要介紹了java 多態(tài)實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01

最新評(píng)論