超碰人人人人人,色婷婷综合久久久久中文一区二区,国产-第1页-浮力影院,欧美老妇另类久久久久久

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

突破Excel百萬數(shù)據(jù)導(dǎo)出瓶頸:全鏈路優(yōu)化實(shí)戰(zhàn)指南

freeflydom
2025年5月9日 9:6 本文熱度 102

在日常工作中,Excel數(shù)據(jù)導(dǎo)出是一個(gè)常見的需求。

然而,當(dāng)數(shù)據(jù)量較大時(shí),性能和內(nèi)存問題往往會(huì)成為限制導(dǎo)出效率的瓶頸。

當(dāng)用戶點(diǎn)擊"導(dǎo)出"按鈕時(shí),后臺(tái)系統(tǒng)往往會(huì)陷入三重困境:

?內(nèi)存黑洞?:某電商平臺(tái)在導(dǎo)出百萬訂單時(shí),因傳統(tǒng)POI方案導(dǎo)致堆內(nèi)存突破4GB,頻繁觸發(fā)Full GC,最終引發(fā)服務(wù)雪崩;
?時(shí)間漩渦?:某物流系統(tǒng)導(dǎo)出50萬運(yùn)單耗時(shí)45分鐘,用戶多次重試導(dǎo)致數(shù)據(jù)庫連接池耗盡;
?磁盤風(fēng)暴?:某金融平臺(tái)導(dǎo)出交易記錄生成1.2GB文件,服務(wù)器磁盤IO飆升至100%;

我們結(jié)合 EPPlus、MiniExcel 和 NPOI 的 C# 高性能 Excel 導(dǎo)出方案對(duì)比及實(shí)現(xiàn)研究一下怎么提高導(dǎo)出效率。

一、技術(shù)方案核心對(duì)比

?特性??EPPlus??MiniExcel??NPOI?
處理模型DOMSAX 流式DOM/流式混合
內(nèi)存占用 (100萬行)1.2GB180MB850MB
文件格式支持.xlsx.xlsx/.csv.xls/.xlsx
公式計(jì)算支持不支持部分支持
模板引擎內(nèi)置模板語法需要擴(kuò)展
異步支持有限完全支持不支持
NuGet 安裝量1.2億+800萬+2.3億+
 

二、各方案選型建議

?場(chǎng)景??推薦方案??示例代碼特征?
簡(jiǎn)單數(shù)據(jù)導(dǎo)出MiniExcel 流式寫入使用 SaveAsAsync + 分塊生成器
復(fù)雜格式報(bào)表EPPlus 模板引擎樣式預(yù)定義 + 分段保存
舊版 Excel 兼容NPOI 流式寫入使用 SXSSFWorkbook
混合型需求MiniExcel + EPPlus 組合模板分離 + 數(shù)據(jù)流式填充
超大數(shù)據(jù)量 (千萬級(jí))分片寫入 + 并行處理多 Task 分片 + 最終合并

三、性能對(duì)比數(shù)據(jù)

測(cè)試項(xiàng)?EPPlusMiniExcelNPOI
100萬行寫入時(shí)間42s18s65s
內(nèi)存峰值1.1GB190MB820MB
文件大小86MB68MB105MB
GC 暫停時(shí)間1.4s0.2s2.1s
線程資源占用

 

四、核心代碼實(shí)現(xiàn)

1. MiniExcel 流式寫入(推薦方案)

// 配置優(yōu)化參數(shù)
var config = new OpenXmlConfiguration
{
    EnableSharedStrings = false, // 關(guān)閉共享字符串表
    AutoFilterMode = AutoFilterMode.None, // 禁用自動(dòng)篩選
    FillMergedCells = false // 不處理合并單元格
};
// 分頁流式寫入
await MiniExcel.SaveAsAsync("output.xlsx", GetDataChunks(), configuration: config);
IEnumerable<IDictionary<string, object>> GetDataChunks()
{
    var pageSize = 50000;
    for (int page = 0; ; page++)
    {
        var data = QueryDatabase(page * pageSize, pageSize);
        if (!data.Any()) yield break;
        
        foreach (var item in data)
        {
            yield return new Dictionary<string, object>
            {
                ["ID"] = item.Id,
                ["Name"] = item.Name,
                ["CreateTime"] = item.CreateTime.ToString("yyyy-MM-dd")
            };
        }
    }
}

優(yōu)化點(diǎn)?:

  • 分頁加載數(shù)據(jù)庫數(shù)據(jù)
  • 延遲加載數(shù)據(jù)生成器
  • 關(guān)閉非必要功能

2. EPPlus 混合寫入方案

using (var package = new ExcelPackage())
{
    var sheet = package.Workbook.Worksheets.Add("Data");
    int row = 1;
    // 批量寫入頭信息
    sheet.Cells["A1:C1"].LoadFromArrays(new[] { new[] { "ID", "Name", "CreateTime" } });
    // 分塊寫入(每50000行保存一次)
    foreach (var chunk in GetDataChunks(50000))
    {
        sheet.Cells[row+1, 1].LoadFromCollection(chunk);
        row += chunk.Count;
        
        if (row % 50000 == 0)
        {
            package.Save(); // 分段保存
            sheet.Cells.ClearFormulas();
        }
    }
    
    package.SaveAs(new FileInfo("output_epplus.xlsx"));
}

3. 性能對(duì)比測(cè)試代碼

[BenchmarkDotNet.Attributes.SimpleJob]
public class ExcelBenchmarks
{
    private List<DataModel> _testData = GenerateTestData(1_000_000);
    [Benchmark]
    public void MiniExcelExport() => MiniExcel.SaveAs("mini.xlsx", _testData);
    [Benchmark]
    public void EPPlusExport() 
    {
        using var pkg = new ExcelPackage();
        var sheet = pkg.Workbook.Worksheets.Add("Data");
        sheet.Cells.LoadFromCollection(_testData);
        pkg.SaveAs("epplus.xlsx");
    }
    [Benchmark]
    public void NPOIExport()
    {
        var workbook = new XSSFWorkbook();
        var sheet = workbook.CreateSheet("Data");
        for (int i = 0; i < _testData.Count; i++)
        {
            var row = sheet.CreateRow(i);
            row.CreateCell(0).SetCellValue(_testData[i].Id);
            row.CreateCell(1).SetCellValue(_testData[i].Name);
        }
        using var fs = new FileStream("npoi.xlsx", FileMode.Create);
        workbook.Write(fs);
    }
}

五、混合方案實(shí)現(xiàn)

1. EPPlus + MiniExcel 組合方案

// 先用 EPPlus 創(chuàng)建帶樣式的模板
using (var pkg = new ExcelPackage(new FileInfo("template.xlsx")))
{
    var sheet = pkg.Workbook.Worksheets[0];
    sheet.Cells["A1"].Value = "動(dòng)態(tài)報(bào)表";
    pkg.Save();
}
// 用 MiniExcel 填充大數(shù)據(jù)量
var data = GetBigData();
MiniExcel.SaveAsByTemplate("output.xlsx", "template.xlsx", data);

2. 分片異步導(dǎo)出方案

public async Task ExportShardedDataAsync()
{
    var totalRecords = 5_000_000;
    var shardSize = 100_000;
    var shards = totalRecords / shardSize;
    var tasks = new List<Task>();
    for (int i = 0; i < shards; i++)
    {
        var start = i * shardSize;
        tasks.Add(Task.Run(async () => 
        {
            using var stream = new FileStream($"shard_{i}.xlsx", FileMode.Create);
            await MiniExcel.SaveAsAsync(stream, QueryData(start, shardSize));
        }));
    }
    await Task.WhenAll(tasks);
    MergeShardFiles(shards);
}
private void MergeShardFiles(int shardCount)
{
    using var merger = new ExcelPackage();
    var mergedSheet = merger.Workbook.Worksheets.Add("Data");
    
    int row = 1;
    for (int i = 0; i < shardCount; i++)
    {
        var shardData = MiniExcel.Query($"shard_{i}.xlsx");
        mergedSheet.Cells[row, 1].LoadFromDictionaries(shardData);
        row += shardData.Count();
    }
    
    merger.SaveAs(new FileInfo("final.xlsx"));
}

六、高級(jí)優(yōu)化策略

1. 內(nèi)存管理配置

// Program.cs 全局配置
AppContext.SetSwitch("System.Buffers.ArrayPool.UseShared", true); // 啟用共享數(shù)組池
// 運(yùn)行時(shí)配置(runtimeconfig.template.json)
{
  "configProperties": {
    "System.GC.HeapHardLimit": "0x100000000", // 4GB 內(nèi)存限制
    "System.GC.HeapHardLimitPercent": "70",
    "System.GC.Server": true
  }
}

2. 數(shù)據(jù)庫優(yōu)化

// Dapper 分頁優(yōu)化
public IEnumerable<DataModel> GetPagedData(long checkpoint, int size)
{
    return _conn.Query<DataModel>(
        @"SELECT Id, Name, CreateTime 
        FROM BigTable 
        WHERE Id > @Checkpoint 
        ORDER BY Id 
        OFFSET 0 ROWS 
        FETCH NEXT @Size ROWS ONLY 
        OPTION (RECOMPILE)", // 強(qiáng)制重新編譯執(zhí)行計(jì)劃
        new { checkpoint, size });
}

3. 異常處理增強(qiáng)

try
{
    await ExportDataAsync();
}
catch (MiniExcelException ex) when (ex.ErrorCode == "DISK_FULL")
{
    await CleanTempFilesAsync();
    await RetryExportAsync();
}
catch (SqlException ex) when (ex.Number == 1205) // 死鎖重試
{
    await Task.Delay(1000);
    await RetryExportAsync();
}
finally
{
    _semaphore.Release(); // 釋放信號(hào)量
}

七、最佳實(shí)踐總結(jié)

?1、數(shù)據(jù)分頁策略?

  • 使用有序 ID 分頁避免 OFFSET 性能衰減
// 優(yōu)化分頁查詢
var lastId = 0;
while (true)
{
    var data = Query($"SELECT * FROM Table WHERE Id > {lastId} ORDER BY Id FETCH NEXT 50000 ROWS ONLY");
    if (!data.Any()) break;
    lastId = data.Last().Id;
}

?2、內(nèi)存控制三位一體?

  • 啟用服務(wù)器 GC 模式
  • 配置共享數(shù)組池
  • 使用對(duì)象池復(fù)用 DTO

3?、異常處理金字塔

try {
    // 核心邏輯
} 
catch (IOException ex) when (ex.Message.Contains("磁盤空間")) {
    // 磁盤異常處理
}
catch (SqlException ex) when (ex.Number == 1205) {
    // 數(shù)據(jù)庫死鎖處理
}
catch (Exception ex) {
    // 通用異常處理
}

 

八、避坑指南

常見陷阱

?EPPlus的內(nèi)存泄漏

// 錯(cuò)誤示例:未釋放ExcelPackage
var pkg = new ExcelPackage(); // 必須包裹在using中
pkg.SaveAs("leak.xlsx");
// 正確用法
using (var pkg = new ExcelPackage())
{
    // 操作代碼
}

NPOI的文件鎖定

// 錯(cuò)誤示例:未正確釋放資源
var workbook = new XSSFWorkbook();
// 正確用法
using (var fs = new FileStream("data.xlsx", FileMode.Create))
{
    workbook.Write(fs);
}

異常處理最佳實(shí)踐

try
{
    await ExportAsync();
}
catch (MiniExcelException ex) when (ex.ErrorCode == "DISK_FULL")
{
    _logger.LogError("磁盤空間不足: {Message}", ex.Message);
    await CleanTempFilesAsync();
    throw new UserFriendlyException("導(dǎo)出失敗,請(qǐng)聯(lián)系管理員");
}
catch (DbException ex) when (ex.IsTransient)
{
    _logger.LogWarning("數(shù)據(jù)庫暫時(shí)性錯(cuò)誤,嘗試重試");
    await Task.Delay(1000);
    await RetryExportAsync();
}
finally
{
    _exportSemaphore.Release();
}

九、典型場(chǎng)景建議?

  1. ?金融報(bào)表? → EPPlus(復(fù)雜公式+圖表)
  2. ?日志導(dǎo)出? → MiniExcel(千萬級(jí)流式處理)
  3. ?舊系統(tǒng)遷移? → NPOI(xls兼容)
  4. ?動(dòng)態(tài)模板? → MiniExcel模板引擎

 

通過合理的方案選擇和優(yōu)化配置,可實(shí)現(xiàn):

  • ?內(nèi)存消耗?降低 80% 以上
  • ?導(dǎo)出速度?提升 3-5 倍
  • ?系統(tǒng)穩(wěn)定性?顯著增強(qiáng)

?轉(zhuǎn)自https://www.cnblogs.com/xiongze520/p/18866690


該文章在 2025/5/9 9:06:12 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved