Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 填充DataAdapter时system.outofmemoryexception?_C#_Asp.net_Visual Studio 2008 - Fatal编程技术网

C# 填充DataAdapter时system.outofmemoryexception?

C# 填充DataAdapter时system.outofmemoryexception?,c#,asp.net,visual-studio-2008,C#,Asp.net,Visual Studio 2008,我必须从数据库中提取150K记录。我使用的是da.Fill(ds,“Query”)及其抛出的system.outofmemoryexception Dim daGrid As New SqlDataAdapter(sqlcmd_q) daGrid.Fill(dsGrid, "Query") daGrid.Dispose() 我只需要这个数据表。我不能使用XML。因为我需要将其分配给MSChartControl以显示ScotterPlot 有什么建议吗?我要检查的第一件事是返回多少列,以及它们的

我必须从数据库中提取
150K
记录。我使用的是
da.Fill(ds,“Query”)
及其抛出的
system.outofmemoryexception

Dim daGrid As New SqlDataAdapter(sqlcmd_q)
daGrid.Fill(dsGrid, "Query")
daGrid.Dispose()
我只需要这个数据表。我不能使用XML。因为我需要将其分配给MSChartControl以显示ScotterPlot


有什么建议吗?

我要检查的第一件事是返回多少列,以及它们的数据类型。虽然150K记录很多,但除非每条记录的长度约为13K(在32位机器上),否则它不应该给您一个OOM异常。这对我来说意味着返回的字段比需要的多,或者可能有些字段是非常大的字符串或二进制数据。尝试减少select语句,以仅返回显示所需的字段


如果这不起作用,您可能需要从DataTable移动到自定义数据类型的列表(具有适当字段的类)。

您没有指定查询。确保它只包含所需的列

如果您仍然有问题,您可以尝试切换到64位(如果您的硬件支持64位,并且您有超过2GB的可用内存)


如果这没有帮助,你必须减少内存占用。一个可能的选择是在不将所有基础数据存储在内存中的情况下渲染绘图。只需逐个加载数据,计算坐标并存储,而不存储底层记录。也许你甚至可以让查询来做这件事。

我知道这个答案对原始海报的帮助已经太晚了,但我希望它能帮助其他遇到类似问题的人

首先,问题出在
DataTable
上,而不是
DataAdapter

问题可能是你真的没有记忆(在这种情况下,我的回答不会有帮助)。您可以通过数学计算来确定这是否是实际情况-记录数x每个记录的字节估计数。如果在32位平台上接近2GB,或者在64位平台上接近可用RAM,那么您唯一的选择就是减少记录数、字段数,或者提出一种使用DataReader而不是DataTable的方法

在你的例子中,你有150k条记录,让我们假设每一条记录都需要1KB的内存,这给了我们一个150MB的整数。即使在具有2GB RAM的32位机器上,这也应该可以(前提是没有太多类似的内存分配)。在您的情况下,您有一台具有128GB RAM(nice)的64位计算机。所以从逻辑上讲,您不应该出现内存不足的错误

那么是什么导致了这个问题呢?它是大型对象堆(LOH)。为什么?
DataTable
创建一个数组来保存这些记录。我的理解是,它创建了一个50的数组,然后随着记录的添加而增长。任何超过85000字节的内存分配都将来自大型对象堆。(您使用的是64位平台,因此,一旦您点击10625条记录,分配将开始来自大型对象堆。)大型对象堆的问题在于它没有被压缩。所以可能有很多可用空间,但没有足够大的单个连续块。通过.NET4.5,微软在合并相邻片段方面对其进行了改进,但不会重新组织这些片段以创建更大的可用空间块。最终的结果是,在我的经验中,一旦你误入LOH,你就会出现记忆缺失异常,这只是时间问题

解决方案是什么

对我来说,有效的方法是设置
数据表的初始容量。从数据库中提取记录时,这意味着首先要进行计数,因此这需要额外的数据库查询,然后:

.
.
dsGrid.InitialCapacity = count;
daGrid.Fill(dsGrid, "Query");
.
.
虽然这并不能避免误入LOH,但这应该意味着它只进行一次分配,而不是多次分配。因此,除了避免内存不足异常之外,您还应该获得性能增益(由额外数据库查询的需要抵消)

您可以让.net垃圾收集器压缩大对象堆,但只能在下次运行时告诉它这样做。如果我知道我正在进入大对象堆,我倾向于使用这个。这可能是多余的,但考虑修改我的上述建议:

.
.
dsGrid.InitialCapacity = count;
if (count > 10625)
{
    System.Runtime.GCSettings.LargeObjectHeapCompactionMode =
        System.Runtime.GCLargeObjectHeapCompactionMode.CompactOnce;
}
daGrid.Fill(dsGrid, "Query");
.
.

以合理的方式聚合数据…这些记录有多大(以字节为单位)?我觉得有点奇怪。在我的例子中,我有一台64位的机器,有128GB内存和1.8T磁盘。这个表有300万行,大约800MB。我一直都很高兴。但是,这不会发生在另一台内存较少(64GB)的机器上。我不知道这是怎么回事。
或者某些字段是非常大的字符串或二进制数据
假设您有100列,所有列都定义为
VARCHAR(MAX)
,但没有任何值超过10个字符。如果DB列都是
VARCHAR(10)
,会有什么不同吗?我想不会。仅当单元格中的实际值“非常大”时,对吗?@sab669 correct-客户机上varchar(max)的内存利用率应该是(或多或少)实际数据长度,而不是列的大小。