EPPlus大型数据集的内存问题,出现内存不足异常

12

系统内存不足异常。我发现只有在保存时才刷新了内存流。我们有1.5-2GB的数据集。

我正在使用EPPlus版本3.1.3.0。

我们在代码中执行以下操作:

我们循环遍历

     --> Create a Package
        --> each table in the datareader
            -->   Add WorkSheet to the Package 
        --> Dispose Each table.
     --> Save the  Package.
每个Datatable的大小为300Mg,最多可以从系统中导出15个表格。
这会导致一个问题,我已经在https://epplus.codeplex.com/workitem/15085上详细记录了这个问题。
我仍然希望能够使用EPPlus,它非常好用。但是,是否有更好的方法在将工作表添加到包中后释放它?
谢谢您的帮助。
6个回答

17

我也遇到了这个问题,但是通过将"平台目标"选项从x86更改为x64或者"任何CPU"来解决了它。(右键单击项目,然后选择“属性”,然后选择“生成”选项卡,在“平台目标”中选择“x64”)

问题在于对于x86平台,你只能使用大约1.8 GB的RAM。而对于x64平台,你没有这个限制。


1
这对我也起作用了。我有一个包含210,000条记录的Excel电子表格,一直出现内存不足异常。起初我以为是因为我在并行处理大量数据;重新编译为x64模式后问题得到解决。 - user3810900

9
不幸的是,这似乎是EPPlus的一个重大限制。您可以在其codeplex页面上找到其他人发布有关此问题的帖子。当我导出大型数据集 - 单个表格具有115列以上和60,000行以上时,我遇到了类似的问题。通常在30到35k行左右时它就会耗尽内存。发生的情况是每个创建的单元格都是自己的对象,在小数据集中这是可以接受的,但在我的情况下,它将是115x60K = 〜7百万个对象。由于每个单元格都是具有内容(大多数为字符串)的对象,因此它的内存占用量快速增加。
在将来的某个时间点,我的计划是使用Linq2Xml手动创建XML文件。 xlsx只是一个使用XML文件组成工作簿和工作表内容的zip文件重命名而已。因此,您可以使用EPP创建一个空的xlsx,保存它,将其作为zip打开,提取sheet1.xml并通过字符串操作添加数据内容。您还需要处理Excel用于帮助保持文件大小的sharedstring.xml文件。还可能需要更新其他xml文件以进行键或名称等方面的更新。
如果将任何xlsx重命名为.zip扩展名,则可以查看此内容。
示例sheet1.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">
    <dimension ref="A1:C2"/>
    <sheetViews>
        <sheetView tabSelected="1" workbookViewId="0">
            <selection activeCell="C5" sqref="C5"/>
        </sheetView>
    </sheetViews>
    <sheetFormatPr defaultRowHeight="15" x14ac:dyDescent="0.25"/>
    <sheetData>
        <row r="1" spans="1:3" x14ac:dyDescent="0.25">
            <c r="A1" t="s">
                <v>0</v>
            </c><c r="B1" t="s">
                <v>1</v>
            </c><c r="C1" t="s">
                <v>0</v>
            </c>
        </row>
        <row r="2" spans="1:3" x14ac:dyDescent="0.25">
            <c r="A2" t="s">
                <v>1</v>
            </c><c r="B2" t="s">
                <v>0</v>
            </c><c r="C2" t="s">
                <v>1</v>
            </c>
        </row>
    </sheetData>
    <pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>
</worksheet>

示例 sharedstrings.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="6" uniqueCount="2">
    <si>
        <t>AA</t>
    </si>
    <si>
        <t>BB</t>
    </si>
</sst>

您可以在我的另一篇文章中看到我如何进行XML操作:

使用EPPLUS创建数据透视表筛选器

很抱歉我不能给您更好的答案,但希望这能有所帮助。


0

如果您将流传递给ExcelPackage,请注意。在我的情况下,我有一个Windows服务,使用内存流加载包。现在,该服务在一段时间后崩溃并出现OutOfMemory异常。

原因:ExcelPackage的处理不会处理流!

解决方案:

using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(excelSheetBase64)))
using (ExcelPackage excelPackage = new ExcelPackage(ms))
{
    // Your code
}

0
在我的情况下,我在x86平台上使用了EPPlus 7.0.1,有4个表格,总共约10万行。当在ExcelWorksheet上调用sheet.Cells.AutoFitColumns()时,它消耗了另外300MB的内存,并抛出了OutOfMemoryException异常。
如果你的内存有限,请考虑不使用该方法。

0

@Ernie关于当前版本的EPPlus的一些限制是正确的。他们已经承认了这一点,并一直在努力修复它。这让您有两个可能的选择来使其工作:

1)切换到EPPlus 4.0 Beta,他们已经解决了这个问题,以及其他一些问题(尽管您将使用beta版本)。

2)ExcelPackageExcelWorksheet类都实现了IDisposable,因此如果您将它们的使用包装在using()语句中,您可能会获得更好的性能。


2
有没有任何文档显示它在 beta 4 中被修复了?对我来说没有任何区别 - 尽管这是几个月前的事了。虽然希望它能得到修复,但看起来似乎需要对核心引擎进行重大改进。我总是使用 IDisposable(通过 Using's),这对我来说没有任何影响。问题在于包/工作簿会一直保留在内存中,直到完全关闭为止。我甚至尝试通过一系列的打开-保存-关闭-重新打开-添加来逐步导出数据,但并没有什么不同。这是一切或无事可做之事 - 一旦打开文件,就会全部加载。再次强调,希望我的想法能够被证明是错误的。 - Ernie S
EPPlus 4.1.0并不能解决这个问题。如果你只有一个工作表需要写入,那么释放也无济于事。 - Heiner

0

这个问题有时会在调试大量数据时出现。

如果您在服务器上尝试应用程序,使用真正的IIS或者如果您拥有Win PRO版本,则可以在您的PC上使用真正的IIS。

OutOfMemoryException的问题不会发生。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接