【问题标题】:Web Service Out of Memory Exception while filling ADO.Net DataSet填充 ADO.Net 数据集时 Web 服务内存不足异常
【发布时间】:2010-10-27 12:08:35
【问题描述】:

1) ClientApp 对 ASP.Net 2.0 WebService 进行异步调用 2)Web服务调用SQL Server 2005存储过程 3)存储过程返回数据输出,150MB表

在尝试为新行分配更多内存时,DataAdapter.Fill(...) 抛出内存不足异常。

IIS 应用程序池对其没有任何最大内存限制。

是否在 IIS 级别的其他地方设置了最大内存利用率上限? 150MB 的 db 表作为 DataSet 读入内存时会占用更多空间吗? 是否存在这样的场景(可能使用 WCF),过程的结果永远不必驻留在 Web 服务器内存中,而是直接流式传输到客户端?

我不希望将请求拆分为更小的数据集,因为客户端异步请求它们。收集所有部分也必须异步进行,每个客户端都必须为每次调用实现异步收集。

我们将不胜感激任何建议、最佳做法或提示。

【问题讨论】:

  • 几个问题。 1) 这是托管在 32 位版本的 Windows Server 上吗? 2)应用程序池工作进程崩溃时有多大?

标签: asp.net sql-server wcf ado.net iis-6


【解决方案1】:

是的,使用 DataSet 比实际数据使用更多的内存。多少很难量化,但 StackOverflow 上的this 问题表明是原始数据大小的 4 倍以上。让我们假设这是正确的。 150MB 数据乘以 4 = 600MB 内存。当 ASP.NET 应用程序使用大约 800MB 的 RAM 时,它们将开始抛出 OutOfMemoryExceptions。我不确定该限制与应用程序池内存限制如何相同。您是否尝试过 boot.ini 中的 /3GB 开关? (有关说明,请参阅this article

另请注意,如果您正在序列化您的 DataSet,序列化程序可能会为序列化分配巨大的缓冲区(最多为原始大小的 10 倍,请参阅this article。您指出在读取数据时会出现问题,所以这是可能不是您的错误的原因(但可能是您解决了内存不足错误并尝试通过网络发送数据)。

我对 DataSet 的体验是,起初它们似乎是个好主意,但您很快就会遇到问题。

另一个(可能更好)的解决方案是使用 DataReader 并一次读取一行。返回成批的行(即对数据使用某种分页)并试验每个批次的大小以找到性能和内存使用之间的最佳点。 WCF 流式传输可能会解决问题,但您需要正确配置 WCF 以允许它在一次调用中返回如此大量的数据。

【讨论】:

    【解决方案2】:

    最佳做法是 a) 不要返回太多数据,b) 使用 WCF 而不是四年前的技术(ASMX Web 服务)。

    【讨论】:

    • WCF 如何处理 ADO.Net DataSet.Fill() 异常?内存不足发生在数据集完全加载到 Web 服务器内存之前。它甚至还没有开始被序列化以作为 Web 服务响应进行传输。是否可以将 WCF 配置为直接从 SQL 将数据流式传输到客户端,而无需将其全部加载到 DataSet 的内存中?
    • 我知道 WCF 可以通过返回 System.IO.Stream 进行流式传输。更糟的是,您可以使用 ExecuteReader。然后在输出 Stream 上构造一个 XmlWriter,对于通过 Read 返回的每一行,写入一个包含内容的 XML 元素。这是更多的代码,但应该可以工作。可能还有更好的方法。您真的需要在一次调用中返回全部 150MB 吗?
    猜你喜欢
    • 1970-01-01
    • 2010-09-13
    • 1970-01-01
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多