0

在我们的应用程序中,我们使用Windows Service生成报告。报告的数据是使用存储过程从SQL Server获取的。在某些情况下,返回的结果集包含 250,000 条记录(我们对此无能为力,我们需要一次性使用这些数据,因为我们需要对此进行一些计算)。

问题

我们的应用程序正在阅读器中获取此数据,并且我们正在将此数据集转换为自定义对象的自定义集合。由于数据量很大,它无法将完整的数据存储在自定义对象中,从而导致内存不足。当我们在执行记录时看到任务管理器的进程使用率时,它会变得非常高,甚至是 CPU 使用率。

我不确定在这种情况下应该怎么做。

  1. 我们可以增加分配给在 CLR 下运行的单个进程的内存大小吗?
  2. 还有其他解决方法吗?

任何帮助将非常感激

  1. 为什么我一次需要所有数据:我们需要对完整的结果集进行计算
  2. 我们正在使用 ADO.NET 并将数据集转换为我们的自定义对象(集合)
  3. 我们的系统是 32 位的
  4. 我们无法分页数据
  5. 无法将计算移至 sql server

此堆栈跟踪可能会有所帮助:

引发了“System.OutOfMemoryException”类型的异常。服务器堆栈跟踪:在 System.Collections.Generic.Dictionary 2.ValueCollection.System.Collections.Generic.IEnumerable<TValue>.GetEnumerator() at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext() 在 System.Collections.Generic.List 1.InsertRange(Int32 index, IEnumerable1 集合)在 System.Collections.Generic.List 1.AddRange(IEnumerable1 集合)在 MyProject.Common.Data.DataProperty.GetPropertiesForType(在 C:\Ashish-Stuff\Projects\HCPA\Dev Branch\Common\Benefits.Common\Data\DataProperty.shared.cs 中键入 t):MyProject.Common.Data.Extensions.GetProperties[T](T 目标的第 60 行) 在 C:\Ashish-Stuff\Projects\HCPA\Dev Branch\Common\Benefits.Common\Data\Extensions.shared.cs:第 30 行在 MyProject.Common.Data.Factories.SqlServerDataFactoryContract 1.GetData(String procedureName, IDictionary2 个参数,Nullable 1 languageId, Nullable1 pageNumber,Nullable `1 pageSize)

谢谢,阿希什

4

3 回答 3

0

你能每 1000 行数据,将你自定义的对象集合序列化到磁盘的某个地方吗?然后当你返回数据时,从那些文件中分页?

有关您的用例为何需要撤回 250 万行数据的更多信息会有所帮助。

于 2012-07-23T15:07:25.387 回答
0

我的第一个想法是可以通过一些存储过程在 Sql-Server 端进行计算。我怀疑这种方法需要一些 Sql-Server 绝地......但无论如何,你考虑过这种方法吗?

于 2012-07-23T16:00:42.493 回答
0

我很想看到一个代码示例突出显示您从哪里得到这个错误。它是在数据本身上(填充阅读器)还是创建对象并将其添加到自定义集合(填充集合)。

我之前也遇到过类似的问题,处理非常大的数据集,但是在尽可能长时间地将其留在流中时取得了巨大的成功。流会将数据直接保存在内存中,并且在您完成构建对象之前,您永远不会真正拥有可以直接访问整个混乱的任何东西。现在,鉴于堆栈跟踪显示“MoveNext”操作的错误,这可能不适合您。然后我会说尝试分块数据,一次抓取 10k 行之类的,我知道这可以用 SQL 来完成。不过,这会使读取数据需要更长的时间。

编辑

如果您将其从数据库读取到本地流中,然后传递(注意不要关闭它),那么您不应该遇到这些问题。创建一个数据包装类,您可以使用开放流和开放阅读器传递该类。将数据存储在流中,然后使用包装函数从中读取您需要的特定数据。诸如GetSumOfXField()orAverageOfYValues()等​​之类的东西……数据永远不会存在于活动对象中,但是您不必为此继续返回数据库。

伪示例

    public void ReadingTheDataFunction()
    {
        DBDataReader reader = dbCommand.ExecuteReader();
        MyDataStore.FillDataSource(reader)
    }

    private void FillDataSource(DbDataReader reader)
    {
        StreamWriter writer = new StreamWriter(GlobaldataStream);
        while (reader.Read())
            writer.WriteLine(BuildStringFromDataRow(reader));
        reader.close();
    }

    private CustomObject GetNextRow()
    {
        String line = GlobalDataReader.ReadLine();
        //Parse String to Custom Object
        return ret;
    }

从那里你绕过 MyDataStore,只要流和阅读器没有关闭,你就可以移动你的位置,去寻找单个条目,编译总和和平均值等等,你甚至不需要知道你是' 不处理活动对象,只要您仅通过接口函数与它交互。

于 2012-07-23T19:37:22.967 回答