成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Excel高性能導(dǎo)出方案!

開發(fā) 前端
很多小伙伴門在開發(fā)數(shù)據(jù)導(dǎo)出功能時(shí),習(xí)慣性使用Apache POI的HSSF/XSSF組件。這類方案在數(shù)據(jù)量超過5萬行時(shí),會(huì)出現(xiàn)明顯的性能斷崖式下跌。根本原因在于內(nèi)存對象模型的設(shè)計(jì)缺陷:每個(gè)Cell對象占用約1KB內(nèi)存,百萬級(jí)數(shù)據(jù)直接導(dǎo)致JVM堆內(nèi)存爆炸。

前言

在我們的日常工作中,經(jīng)常會(huì)有Excel數(shù)據(jù)導(dǎo)出的需求。

但可能會(huì)遇到性能和內(nèi)存的問題。

今天這篇文章跟大家一起聊聊Excel高性能導(dǎo)出的方案,希望對你會(huì)有所幫助。

1.傳統(tǒng)方案的問題

很多小伙伴門在開發(fā)數(shù)據(jù)導(dǎo)出功能時(shí),習(xí)慣性使用Apache POI的HSSF/XSSF組件。

這類方案在數(shù)據(jù)量超過5萬行時(shí),會(huì)出現(xiàn)明顯的性能斷崖式下跌。

根本原因在于內(nèi)存對象模型的設(shè)計(jì)缺陷:每個(gè)Cell對象占用約1KB內(nèi)存,百萬級(jí)數(shù)據(jù)直接導(dǎo)致JVM堆內(nèi)存爆炸。

示例代碼(反面教材):

// 典型內(nèi)存殺手寫法
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
for (int i = 0; i < 1000000; i++) {
    Row row = sheet.createRow(i); // 每行產(chǎn)生Row對象
    row.createCell(0).setCellValue("數(shù)據(jù)"+i); // 每個(gè)Cell獨(dú)立存儲(chǔ)
}

這種寫法會(huì)產(chǎn)生約100萬個(gè)Row對象和1000萬個(gè)Cell對象(假設(shè)每行10列),直接導(dǎo)致內(nèi)存占用突破1GB。

更致命的是頻繁Full GC會(huì)導(dǎo)致系統(tǒng)卡頓甚至OOM崩潰。

2.流式處理架構(gòu)設(shè)計(jì)

高性能導(dǎo)出的核心在于內(nèi)存與磁盤的平衡

這里給出兩種經(jīng)過生產(chǎn)驗(yàn)證的方案:

方案一:SXSSFWorkbook

使用SXSSFWorkbook類,它是Apache POI的增強(qiáng)版。

具體示例如下:

// 內(nèi)存中只保留1000行窗口
SXSSFWorkbook workbook = new SXSSFWorkbook(1000); 
Sheet sheet = workbook.createSheet();
for (int i = 0; i < 1000000; i++) {
    Row row = sheet.createRow(i);
    // 寫入后立即刷新到臨時(shí)文件
    if(i % 1000 == 0) {
        ((SXSSFSheet)sheet).flushRows(1000); 
    }
}

通過設(shè)置滑動(dòng)窗口機(jī)制,將已處理數(shù)據(jù)寫入磁盤臨時(shí)文件,內(nèi)存中僅保留當(dāng)前處理批次。實(shí)測百萬數(shù)據(jù)內(nèi)存占用穩(wěn)定在200MB以內(nèi)。

方案二:EasyExcel

EasyExcel是阿里巴巴開源的Excel高性能處理框架,目前在業(yè)界使用比較多。

最近EasyExcel的作者又推出了FastExcel,它是EasyExcel的升級(jí)版。

// 極簡流式API示例
String fileName = "data.xlsx";
EasyExcel.write(fileName, DataModel.class)
    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
    .sheet("Sheet1")
    .doWrite(data -> {
        // 分頁查詢數(shù)據(jù)
        int page = 0;
        while (true) {
            List<DataModel> list = queryByPage(page, 5000);
            if (CollectionUtils.isEmpty(list)) break;
            data.write(list);
            page++;
        }
    });

該方案通過事件驅(qū)動(dòng)模型對象復(fù)用池技術(shù),百萬數(shù)據(jù)導(dǎo)出內(nèi)存占用可控制在50MB以下。

其核心優(yōu)勢在于:

  • 自動(dòng)分批加載數(shù)據(jù)(默認(rèn)每批次5000條)
  • 通過反射緩存消除重復(fù)對象創(chuàng)建
  • 內(nèi)置樣式優(yōu)化策略避免內(nèi)存碎片

3.數(shù)據(jù)庫查詢的黃金法則

即便導(dǎo)出工具優(yōu)化到位,若數(shù)據(jù)查詢環(huán)節(jié)存在瓶頸,整體性能仍會(huì)大打折扣。這里給出三個(gè)關(guān)鍵優(yōu)化點(diǎn):

3.1 解決深度分頁問題

傳統(tǒng)分頁查詢在百萬級(jí)數(shù)據(jù)時(shí)會(huì)出現(xiàn)性能雪崩:

SELECT * FROM table LIMIT 900000, 1000 -- 越往后越慢!

正確姿勢應(yīng)使用游標(biāo)方式:

// 基于自增ID的遞進(jìn)查詢
Long lastId = 0L;
int pageSize = 5000;
do {
    List<Data> list = jdbcTemplate.query(
        "SELECT * FROM table WHERE id > ? ORDER BY id LIMIT ?",
        new BeanPropertyRowMapper<>(Data.class),
        lastId, pageSize);
    if(list.isEmpty()) break;
    lastId = list.get(list.size()-1).getId();
    // 處理數(shù)據(jù)...
} while (true);

該方案利用索引的有序性,將時(shí)間復(fù)雜度從O(N2)降為O(N)。

3.2 減少字段數(shù)量

-- 錯(cuò)誤寫法:全字段查詢
SELECT * FROM big_table 

-- 正確姿勢:僅取必要字段
SELECT id,name,create_time FROM big_table

實(shí)測顯示,當(dāng)單行數(shù)據(jù)從20個(gè)字段縮減到5個(gè)字段時(shí),查詢耗時(shí)降低40%,網(wǎng)絡(luò)傳輸量減少70%。

3.3 連接池參數(shù)調(diào)優(yōu)

# SpringBoot配置示例
spring:
  datasource:
    hikari:
      maximum-pool-size: 20 # 根據(jù)CPU核數(shù)調(diào)整
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000

導(dǎo)出場景建議使用獨(dú)立連接池,避免影響主業(yè)務(wù)。

連接數(shù)計(jì)算公式:線程數(shù) = CPU核心數(shù) * 2 + 磁盤數(shù)

4.生產(chǎn)級(jí)進(jìn)階技巧

4.1  異步分片導(dǎo)出

想要提升Excel數(shù)據(jù)導(dǎo)出的性能,我們必須使用多線程異步導(dǎo)出的方案。

具體示例如下:

@Async("exportExecutor")
public CompletableFuture<String> asyncExport(ExportParam param) {
    // 1. 計(jì)算分片數(shù)量
    int total = dataService.count(param);
    int shardSize = total / 100000; 

    // 2. 并行處理分片
    List<CompletableFuture<Void>> futures = new ArrayList<>();
    for (int i = 0; i < shardSize; i++) {
        int finalI = i;
        futures.add(CompletableFuture.runAsync(() -> {
            exportShard(param, finalI * 100000, 100000);
        }, forkJoinPool.commonPool()));
    }

    // 3. 合并文件
    CompletableFuture.allOf(futures.toArray(new CompletableFuture)
        .thenApply(v -> mergeFiles(shardSize));
    return CompletableFuture.completedFuture(taskId);
}

通過分治策略將任務(wù)拆解為多個(gè)子任務(wù)并行執(zhí)行,結(jié)合線程池管理實(shí)現(xiàn)資源可控。

4.2 配置JVM參數(shù)

我們需要配置JVM參數(shù),并且需要對這些參數(shù)進(jìn)行調(diào)優(yōu):

// JVM啟動(dòng)參數(shù)示例
-Xmx4g -Xms4g 
-XX:+UseG1GC 
-XX:MaxGCPauseMillis=200
-XX:ParallelGCThreads=4
-XX:ConcGCThreads=2
-XX:InitiatingHeapOccupancyPercent=35

這樣可以有效的提升性能。

導(dǎo)出場景需特別注意:

  • 年輕代與老年代比例建議2:1
  • 避免創(chuàng)建超過50KB的大對象
  • 使用對象池復(fù)用DTO實(shí)例

4.3 整體方案

Excel高性能導(dǎo)出的方案如下圖所示:

圖片圖片

用戶點(diǎn)擊導(dǎo)出按鈕,會(huì)寫入DB,生成一個(gè)唯一的任務(wù)ID,任務(wù)狀態(tài)為待執(zhí)行。

然后后臺(tái)異步處理,可以分頁將數(shù)據(jù)寫入到Excel中(這個(gè)過程可以使用多線程實(shí)現(xiàn))。

將Excel文件存儲(chǔ)到云存儲(chǔ)中。

然后更新任務(wù)狀態(tài)為以完成。

最后通過WebSocket通知用戶導(dǎo)出結(jié)果。

5.總結(jié)

經(jīng)過多個(gè)千萬級(jí)項(xiàng)目的錘煉,我們總結(jié)出Excel高性能導(dǎo)出的黃金公式:

高性能 = 流式處理引擎 + 分頁查詢優(yōu)化 + 資源管控

具體實(shí)施時(shí)可參考以下決策樹:

圖片圖片

最后給小伙伴們的三個(gè)忠告:

  1. 切忌過早優(yōu)化:在需求明確前不要盲目選擇復(fù)雜方案
  2. 監(jiān)控先行:務(wù)必埋點(diǎn)記錄導(dǎo)出耗時(shí)、內(nèi)存波動(dòng)等關(guān)鍵指標(biāo)
  3. 兜底策略:始終提供CSV導(dǎo)出選項(xiàng)作為保底方案

希望本文能幫助大家在數(shù)據(jù)導(dǎo)出的戰(zhàn)場上,真正實(shí)現(xiàn)"百萬數(shù)據(jù),彈指之間"!

責(zé)任編輯:武曉燕 來源: 蘇三說技術(shù)
相關(guān)推薦

2025-05-12 00:00:00

2025-04-02 08:21:10

2019-03-01 11:03:22

Lustre高性能計(jì)算

2017-11-28 17:14:16

華為云

2020-03-23 14:35:28

前端架構(gòu)應(yīng)用程序

2009-07-31 11:41:12

光纖連接數(shù)據(jù)中心

2009-04-03 11:26:12

AMD上海皓龍

2024-09-12 17:23:02

2022-11-24 10:55:32

2011-07-26 09:36:55

Sencha Touc

2017-07-10 17:25:40

開發(fā)單號(hào)高可用

2009-01-07 01:34:10

SunHPC高性能計(jì)算

2009-06-15 09:23:11

光纖接入機(jī)房FTTx

2012-08-03 15:51:37

HillstoneNAT

2016-04-29 18:07:29

移動(dòng)端高性能Weex

2021-04-12 15:10:35

區(qū)塊鏈開發(fā)礦工

2022-08-17 14:19:05

高性能計(jì)算

2022-03-21 14:13:22

Go語言編程

2020-07-16 08:06:53

網(wǎng)關(guān)高性能計(jì)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 青青草综合 | 欧美国产精品 | 国产精品免费在线 | 欧美日韩国产在线观看 | 日韩免费一区二区 | 水蜜桃亚洲一二三四在线 | 2019天天干夜夜操 | av中文在线 | 日韩播放 | 国产乱人伦 | 午夜看电影在线观看 | 九九综合 | 欧美xxxx色视频在线观看免费 | 亚洲国产精品99久久久久久久久 | h网站在线观看 | 黄视频免费观看 | 国产精品一区一区 | 国产精品极品美女在线观看免费 | 久久伊人亚洲 | 亚洲午夜小视频 | 欧美a∨| 久久av一区二区 | 免费精品在线视频 | 久久精品一区二区三区四区 | 国产区视频在线观看 | www久久 | 国产亚洲精品久久久久动 | 伊人伊人网 | 中国一级特黄毛片大片 | 三区在线 | 欧美精品综合在线 | 91免费在线看 | 欧美国产日韩成人 | 中文字幕第7页 | 国产精品网址 | 久草精品视频 | www.免费看片.com | 欧美精品一区三区 | 久久爱黑人激情av摘花 | 亚洲+变态+欧美+另类+精品 | 国产乱码精品1区2区3区 |