公交车上荫蒂添的好舒服的电影-公用玩物(np双xing总受)-公用小荡货芊芊-公与妇仑乱hd-攻把受做哭边走边肉楼梯play-古装一级淫片a免费播放口

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

突破Excel百萬數據導出瓶頸:全鏈路優化實戰指南

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

在日常工作中,Excel數據導出是一個常見的需求。

然而,當數據量較大時,性能和內存問題往往會成為限制導出效率的瓶頸。

當用戶點擊"導出"按鈕時,后臺系統往往會陷入三重困境:

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

我們結合 EPPlus、MiniExcel 和 NPOI 的 C# 高性能 Excel 導出方案對比及實現研究一下怎么提高導出效率。

一、技術方案核心對比

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

二、各方案選型建議

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

三、性能對比數據

測試項?EPPlusMiniExcelNPOI
100萬行寫入時間42s18s65s
內存峰值1.1GB190MB820MB
文件大小86MB68MB105MB
GC 暫停時間1.4s0.2s2.1s
線程資源占用

 

四、核心代碼實現

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

// 配置優化參數
var config = new OpenXmlConfiguration
{
    EnableSharedStrings = false, // 關閉共享字符串表
    AutoFilterMode = AutoFilterMode.None, // 禁用自動篩選
    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")
            };
        }
    }
}

優化點?:

  • 分頁加載數據庫數據
  • 延遲加載數據生成器
  • 關閉非必要功能

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. 性能對比測試代碼

[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);
    }
}

五、混合方案實現

1. EPPlus + MiniExcel 組合方案

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

2. 分片異步導出方案

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"));
}

六、高級優化策略

1. 內存管理配置

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

2. 數據庫優化

// Dapper 分頁優化
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)", // 強制重新編譯執行計劃
        new { checkpoint, size });
}

3. 異常處理增強

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(); // 釋放信號量
}

七、最佳實踐總結

?1、數據分頁策略?

  • 使用有序 ID 分頁避免 OFFSET 性能衰減
// 優化分頁查詢
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、內存控制三位一體?

  • 啟用服務器 GC 模式
  • 配置共享數組池
  • 使用對象池復用 DTO

3?、異常處理金字塔

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

 

八、避坑指南

常見陷阱

?EPPlus的內存泄漏

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

NPOI的文件鎖定

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

異常處理最佳實踐

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

九、典型場景建議?

  1. ?金融報表? → EPPlus(復雜公式+圖表)
  2. ?日志導出? → MiniExcel(千萬級流式處理)
  3. ?舊系統遷移? → NPOI(xls兼容)
  4. ?動態模板? → MiniExcel模板引擎

 

通過合理的方案選擇和優化配置,可實現:

  • ?內存消耗?降低 80% 以上
  • ?導出速度?提升 3-5 倍
  • ?系統穩定性?顯著增強

?轉自https://www.cnblogs.com/xiongze520/p/18866690


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

主站蜘蛛池模板: 91精品国产免费久久久久 | 国产激情视频在线观看免费播放 | 国产精品白浆在线播放 | 韩国免费a级作爱片在线观看 | 国产成人精品一区二区三在线观看 | 国产作爱视频免费 | 国产精品一区 | 91精品无码 | 99久久精品免费观看国产 | 国产免费午夜a无码v视频 | 国产自制在线观看视频 | 精品无人区一区二区三区 | 国产麻豆成av人片在线观看 | 国产经典视频sm调教 | 变态捆绑在线dvd | 国产欧美综合在线区专区 | 国产成人乱码一二三区18 | 国产一区二区三区丝袜精品 | 极品尤物国产在线播 | 91亚洲精品麻豆 | 国产精品无码片在线看 | www.国产日本视频 | 国产亚洲日韩在线播放人成 | 国产成人av无码精品 | 国产精品毛片 | av午夜片在线观看 | 东京热av加勒比一区二区 | 国产一区二区三区三级电影 | 调教女孩自慰网站免费观看 | 国产午夜精品无码免费不卡影院 | 国产成人小午夜视频在线观看 | 国产一区丝袜在线播放无弹窗 | 国产精品兄妹伦理片一区二区 | 国产一区在线播放 | 国产精品免费视频网 | 国产成人啪精 | 2025中文字幕在线永久免费 | 91久久精品无码一区二区 | 国产精品免费福利久久 | 国产精品伊人久久久久 | 国产成人亚洲欧美日韩 |