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

java之CSV大批量數(shù)據(jù)入庫的實現(xiàn)

 更新時間:2023年02月05日 11:11:01   作者:邱可愛  
本文主要介紹了java之CSV大批量數(shù)據(jù)入庫的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

需求

讀200+的CSV/EXCEL文件,按文件名稱存到不同數(shù)據(jù)庫

前期準(zhǔn)備

環(huán)境

maven + jdk8 + mysql

代碼展示

pom文件

    <dependencies>
        <!--https://mvnrepository.com/artifact/com.opencsv/opencsv -->
        <dependency>            //讀取csv文件 
            <groupId>com.opencsv</groupId>
            <artifactId>opencsv</artifactId>
            <version>${opencsv.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--mybatis-plus 持久層-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>

        <!-- velocity 模板引擎, Mybatis Plus 代碼生成器需要 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>${velocity.version}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

關(guān)鍵代碼及思路

多線程處理數(shù)據(jù),否則8k萬數(shù)據(jù)太慢了

創(chuàng)建線程池,個數(shù)的大小一般取決于自己電腦配置,以及I/O還是CPU密集型。

  • I/O密集型:CPU*2 + 1
  • CPU密集型:CPU + 1
  • Java查看CPU數(shù)目
public static final Integer N_Thread = Runtime.getRuntime().availableProcessors() * 2 + 1;
 ExecutorService service = Executors.newFixedThreadPool(N_Thread );
 List<CompletableFuture<Void>> futureList = new ArrayList<>();

數(shù)據(jù)進(jìn)行分批處理,如果數(shù)據(jù)一次過大,可能導(dǎo)致sql拼接失敗或者程序連接超時的問題。

            List<AirStationHourEntity> records = new ArrayList<>(table.values());
            int basic = 0, total = records.size();

            do{
                int finalBasic = basic;
                String finalTableName = tableName;
                CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
                    List<AirStationHourEntity> subRecords = records.subList(finalBasic * 6000, Math.min((1 + finalBasic) * 6000, total));
                    airStationHourMapper.saveOrUpdateBatch(finalTableName, subRecords);
                }, service);
                // 加入線程集合,方便后續(xù)阻塞主線程,防止線程沒跑就提前結(jié)束
                futureList.add(completableFuture);
                basic++;
            }while (basic * 6000 < total);

獲取文件數(shù)據(jù)

		String url = dataConfig.getStation();
        List<String> stationFiles = FileUtils.findFiles(url);
        //遍歷文件
        for (String fileName : stationFiles) {
            try {
                // 讀取文件數(shù)據(jù)
                String path = url.concat(fileName);
                CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8));
                List<String[]> lines = reader.readAll();

根據(jù)文件名創(chuàng)建相應(yīng)數(shù)據(jù)庫

 tableName = fileName.substring(fileName.lastIndexOf("_") + 1, fileName.indexOf(".") - 2);
                tableName = TABLE_PREFIX.STATION_PREFIX.value.concat(tableName);
                if (airStationHourMapper.findTableByName(tableName) == 0) {
                    airStationHourMapper.createNewTable(tableName);
                }

注意:如果在主線程完成之后,沒有對主線程進(jìn)行阻塞,會導(dǎo)致線程池中的線程沒跑完就直接結(jié)束了,需要遍歷線程集合來阻塞主線程

 for (CompletableFuture<Void> future : futureList) {
     future.join();
 }

關(guān)鍵的SQL語句

saveOrUpdateBatch

這里選用Mysql提供的ON DUPLICATE KEY UPDATE來實現(xiàn)更新或者插入,如果primary key 或者 unique key不存在就插入,否則就更新。注意:primary key 和 unique key都存在的時候可能會導(dǎo)致數(shù)據(jù)的更新的異常,這里建議選其中一個最為鍵,否則容易死鎖!見方案選型

 <update id="saveOrUpdateBatch">
        insert into ${tableName}
        (
        <include refid="Base_Column_List"/>
        )
        values
        <foreach collection="records" item="record" separator=",">
            (
            #{record.dataId,jdbcType=VARCHAR},
            #{record.stationId,jdbcType=VARCHAR},
            #{record.dataTime,jdbcType=TIMESTAMP},
            #{record.aqi,jdbcType=INTEGER},
            #{record.priPol,jdbcType=VARCHAR},
            #{record.co,jdbcType=DOUBLE},
            #{record.co24,jdbcType=DOUBLE},
            #{record.no2,jdbcType=INTEGER},
            #{record.no224,jdbcType=INTEGER},
            #{record.so2,jdbcType=INTEGER},
            #{record.so224,jdbcType=INTEGER},
            #{record.o3,jdbcType=INTEGER},
            #{record.o324,jdbcType=INTEGER},
            #{record.o38,jdbcType=INTEGER},
            #{record.o3824,jdbcType=INTEGER},
            #{record.pm10,jdbcType=INTEGER},
            #{record.pm1024,jdbcType=INTEGER},
            #{record.pm25,jdbcType=INTEGER},
            #{record.pm2524,jdbcType=INTEGER}
            )
        </foreach>
        ON DUPLICATE KEY UPDATE
        AQI = VALUES(AQI),pri_pol = VALUES(pri_pol),
        CO = VALUES(CO),CO_24 = VALUES(CO_24),
        NO2 = VALUES(NO2),NO2_24 = VALUES(NO2_24),
        SO2 = VALUES(SO2),SO2_24 = VALUES(SO2_24),
        O3 = VALUES(O3),O3_8 = VALUES(O3_8),O3_8_24 = VALUES(O3_8_24),
        PM10 = VALUES(PM10),PM10_24 = VALUES(PM10_24),
        PM2_5 = VALUES(PM2_5),PM2_5_24 =VALUES(PM2_5_24);
    </update>

方案選型

此方案時間過久,10多個小時大概能完成100w+的數(shù)據(jù);

在程序中查詢數(shù)據(jù)庫中現(xiàn)存的數(shù)據(jù),然后對這些數(shù)據(jù)進(jìn)行更新,其余的進(jìn)行插入

此方案程序代碼看起來較繁瑣。

選用 ON DUPLICATE KEY UPDATE & 多線程來實現(xiàn)批量處理。 問題 在處理最后一些數(shù)據(jù)時,報異常:獲取不到數(shù)據(jù)庫連接,連接超時

解決方案

修改application.yml的sql配置

    hikari:
      connection-timeout: 600000  //時間設(shè)的長一些

當(dāng)即存在primary key 以及 unique key時,出現(xiàn)了死鎖

如果一個表定義有多個唯一鍵(包括唯一索引、主鍵)時,是不安全的。
當(dāng)mysql執(zhí)行INSERT ON DUPLICATE KEY的INSERT時,存儲引擎會檢查插入的行為是否產(chǎn)生重復(fù)錯誤。

org.springframework.dao.DeadlockLoserDataAccessException:
### Error updating database.  Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
### The error may exist in class path resource [mapper/PersonGroupRefMapper.xml]
### The error may involve com.order.addOrder-Inline
### The error occurred while setting parameters
### SQL: insert into t_***(XX,XX,XX,XX,XX,XX) values         (?, ?, ?, ?, ?, ?)         ON DUPLICATE KEY UPDATE XX= VALUES(XX), XX= VALUES(XX), XX= VALUES(XX)
### Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction Deadlock found when trying to get lock; try restarting transaction; nested exception is com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transactio

解決方案

見上面關(guān)鍵SQL,刪除了primary key 留下了unique key重新建表。

見上面關(guān)鍵SQL,刪除了primary key 留下了unique key重新建表。

批量數(shù)據(jù)入庫,當(dāng)SQL語句拼接過長,超過了設(shè)置的最大的限制。

解決方案

批量數(shù)據(jù)入庫時,稍微減少數(shù)據(jù)量再進(jìn)行插入,如6000條數(shù)據(jù)減為4000數(shù)據(jù)之后再批量入庫。

運行結(jié)果

相比之前一天200W+數(shù)據(jù)有了質(zhì)的提升,半小時完成了所有數(shù)據(jù)的預(yù)處理以及入庫。

到此這篇關(guān)于java之CSV大批量數(shù)據(jù)入庫的實現(xiàn)的文章就介紹到這了,更多相關(guān)java CSV大批量入庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • SpringBoot集成JWT實現(xiàn)token驗證的流程

    SpringBoot集成JWT實現(xiàn)token驗證的流程

    Json web token (JWT), 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標(biāo)準(zhǔn)((RFC 7519).這篇文章主要介紹了SpringBoot集成JWT實現(xiàn)token驗證,需要的朋友可以參考下
    2020-01-01
  • Java NIO Selector用法詳解【含多人聊天室實例】

    Java NIO Selector用法詳解【含多人聊天室實例】

    這篇文章主要介紹了Java NIO Selector用法,結(jié)合實例形式分析了Java NIO Selector基本功能、原理與使用方法,并結(jié)合了多人聊天室實例加以詳細(xì)說明,需要的朋友可以參考下
    2019-11-11
  • Java語言實現(xiàn)簡單FTP軟件 FTP上傳下載管理模塊實現(xiàn)(11)

    Java語言實現(xiàn)簡單FTP軟件 FTP上傳下載管理模塊實現(xiàn)(11)

    這篇文章主要為大家詳細(xì)介紹了Java語言實現(xiàn)簡單FTP軟件,F(xiàn)TP本地文件管理模塊的實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Java超詳細(xì)講解SpringMVC如何獲取請求數(shù)據(jù)

    Java超詳細(xì)講解SpringMVC如何獲取請求數(shù)據(jù)

    Spring?MVC?是?Spring?提供的一個基于?MVC?設(shè)計模式的輕量級?Web?開發(fā)框架,本質(zhì)上相當(dāng)于?Servlet,Spring?MVC?角色劃分清晰,分工明細(xì),本章來講解SpringMVC如何獲取請求數(shù)據(jù)
    2022-04-04
  • 詳解SpringIOC容器相關(guān)知識

    詳解SpringIOC容器相關(guān)知識

    這篇文章主要記錄自己在狂神說java中的學(xué)習(xí)情況,文章里有自己學(xué)習(xí)的理解和擴展,新手難免有理解偏差或者錯誤,懇請大佬指正下,需要的朋友可以參考下
    2021-05-05
  • java拋出異常后,后續(xù)代碼是否繼續(xù)執(zhí)行詳解

    java拋出異常后,后續(xù)代碼是否繼續(xù)執(zhí)行詳解

    這篇文章主要給大家介紹了關(guān)于java拋出異常后,后續(xù)代碼是否繼續(xù)執(zhí)行詳?shù)南嚓P(guān)資料,在Java編程中,異常是當(dāng)程序執(zhí)行時遇到問題時拋出的一種特殊情況,需要的朋友可以參考下
    2023-07-07
  • Spring中filter過濾器的定義方法

    Spring中filter過濾器的定義方法

    這篇文章主要介紹了Spring中filter過濾器的定義方法,Filter 程序是一個實現(xiàn)了特殊接口的 Java 類,與 Servlet 類似,也是由 Servlet 容器進(jìn)行調(diào)用和執(zhí)行的,需要的朋友可以參考下
    2023-08-08
  • 淺談java socket的正確關(guān)閉姿勢

    淺談java socket的正確關(guān)閉姿勢

    這篇文章主要介紹了java socket的正確關(guān)閉姿勢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Springboot自定義mybatis攔截器實現(xiàn)擴展

    Springboot自定義mybatis攔截器實現(xiàn)擴展

    本文主要介紹了Springboot自定義mybatis攔截器實現(xiàn)擴展,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 使用Java實現(xiàn)KMZ和KML數(shù)據(jù)的直接解析

    使用Java實現(xiàn)KMZ和KML數(shù)據(jù)的直接解析

    本文主要講解如何用JAVA語言,直接解析KMZ數(shù)據(jù),文章首先介紹google地圖中的KMZ和KML數(shù)據(jù),然后使用代碼的方式實現(xiàn)數(shù)據(jù)的解析,最后展示解析成果以及如何將數(shù)據(jù)轉(zhuǎn)換成空間WKT數(shù)據(jù),需要的朋友可以參考下
    2024-06-06

最新評論

临武县| 隆昌县| 抚州市| 疏附县| 瑞丽市| 南昌县| 西林县| 财经| 莱西市| 文成县| 九龙县| 开封市| 临武县| 阿拉善右旗| 和平县| 平遥县| 垫江县| 新巴尔虎右旗| 内丘县| 岳阳县| 收藏| 周至县| 宁远县| 昌平区| 凤凰县| 灵石县| 新晃| 阜阳市| 专栏| 来安县| 延边| 安福县| 凤翔县| 北安市| 当阳市| 静宁县| 衡山县| 革吉县| 泗洪县| 滨州市| 峨眉山市|