从数据库中拉取大量数据时遇到内存不足异常

3

我们正在从SQL Server数据库中提取大量数据。它大约有25000行和2500列。要求是读取数据并将其导出到电子表格,因此无法选择分页。当记录较少时,它能够提取数据,但当它增长到我上面提到的大小时,它会抛出异常。

public DataSet Exportexcel(string Username)
{
    Database db = DatabaseFactory.CreateDatabase(Config);
    DbCommand dbCommand = 
        db.GetStoredProcCommand("Sp_ExportADExcel");
    db.AddInParameter(dbCommand, "@Username", DbType.String, 
        Username);
    return db.ExecuteDataSet(dbCommand);
}

请帮我解决这个问题。

你能通过提取1000行数据并检查返回的DataSet大小来计算数据集大小吗?然后乘以25并检查你的服务器是否有足够的内存。请注意,ASP.NET、IIS和Windows Server架构可能会有一些限制,因此如果你遇到任何这些限制的问题,即使服务器有2 TB的RAM也无济于事...但首先要检查你的实际数字... - Davide Piras
为什么不编写一个查询来限制从数据库中获取的行数。重复此操作,直到导出所有行。 - onatm
2
你需要流式传输数据,将其导出到离线 DataSet 中,使用 DataReader 迭代遍历记录集中的每一行,这样就不会一次性占用过多内存。 - Mantorok
你不能将数据块写入电子表格吗? - Renatas M.
请查看这个问题,它可能会帮助您:http://stackoverflow.com/questions/1662982/why-am-i-getting-an-out-of-memory-error-doing-asp-net-excel-interop - huMpty duMpty
避免将数据作为“DataTable”获取。相反,从数据库中流式传输结果并直接传输到浏览器。 - Steven
4个回答

4
要求读取数据并将其导出到电子表格中,因此分页不是一个选择。
为什么不逐步读取数据呢?而不是一次性获取所有记录,为什么不每次获取有限数量的记录并将它们写入Excel中。继续进行,直到处理完所有记录为止。

这是我唯一的选择,因为在这种情况下,我需要解析结果并逐个写入Excel。现在我直接将其绑定到GridView并呈现为电子表格。 - Jeeva
所以你想要简单的方法 :) 你应该在问题中提到这一点。 - Renatas M.
在我看来,一次在 GridView 中显示 25000 条记录是没有意义的。我有一种感觉,你这样做只是为了导出到 Excel。 - Haris Hasan

1

你的问题纯粹是因为你试图一次性提取太多数据。

你可以通过在执行查询的机器上安装更多内存来解决这个问题,但这只是一个权宜之计。

最好分步骤检索这么多数据。

你可以很容易地逐行读取数据,并将其以CSV格式导出/追加到文件中,所有这些都可以在存储过程中完成。

你没有说你使用的是哪种数据库,但处理如此大量的数据是数据库引擎设计的应对之策。

除此之外,在处理大量数据对象的C#代码时,最好研究使用泛型,因为这不会像类一样强制进行对象实例化,从而减少了内存占用。


0

你可以使用批处理逻辑每次获取5000个记录并将结果存储在临时数据集中,一旦所有处理完成后,将临时数据集中的数据转储到Excel中。

你可以使用C# BulkCopy类完成此操作。


0

如果只需要将数据作为 CSV 文件在 Excel 中使用,可以使用批量复制。

bcp "select col1, col2, col3 from database.schema.SomeTable" queryout  "c:\MyData.txt"  -c -t"," -r"\n" -S ServerName -T

这个速度更快,占用空间很小。


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