繁体   English   中英

C#system.outofmemoryException

[英]C# system.outofmemoryexception

我必须处理一个有两列和80000行的表。我需要在该表的两列之间进行比较,这导致运行时出现system.out of memory异常。

我将比较第一个记录值和其余79,999 条记录,即(1,1),(1,2,.....(1,79999),(2,1),(2,2),。 ...(2,79999)...(3,1),(3,2),....(3,79999)...

如何处理这种情况

提前致谢

这是我的代码:

SqlCommand cmd = new SqlCommand("select (g.gene),n.goterm,(n.gene) from genematrix g  join genematrix n on n.goterm=g.goterm where g.id<n.id", con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);

表名GeneMatrix:

GoTerm    Gene

1a       gene1
2b       gene1
1a       gene2
2b       gene3

直到80000条记录...........

上面的是表结构,我将根据该表结构将第一个基因记录与所有其他基因记录进行比较,然后查找第二个基因记录,并开始将其与所有其他记录进行比较...如此直到最后一个基因。

当我比较gene1和gene2的通用术语时,结果就像

gene1 gene2 1a
gene1 gene3 2b

我上面的查询正确地返回了输出,但是问题是..a system.outofmemoryexception被显示,并且直到结束我都无法完全运行查询。

检查您正在构建的是64位进程,而不是32位进程,这是Visual Studio的默认编译模式。 为此,请在项目上,右键单击属性->构建->平台目标:x64。 与任何32位进程一样,以32位编译的Visual Studio应用程序的虚拟内存限制为2GB。

64位进程没有此限制,因为它们使用64位指针,因此它们的理论最大地址空间为16艾字节(2 ^ 64)。 实际上,Windows x64将进程的虚拟内存限制为8TB。 然后,内存限制问题的解决方案是使用64位编译。

但是,默认情况下,Visual Studio中的对象大小仍限制为2GB。 您将能够创建多个阵列,其总大小将大于2GB,但是默认情况下您将无法创建大于2GB的阵列。 希望,如果您仍想创建大于2GB的阵列,可以通过将以下代码添加到app.config文件中来实现:

<configuration>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>

我认为您描述的问题不正确。 您从具有2列的表开始,但是您的代码段加载了3列的联接。

请显示导致OutOfMemory异常的行。

理论1.运行一个计数查询:从n.goterm = g.goterm上的genematrix g joingenematrix n中选择count(g.gene),其中g.id

理论2。如果加载记录是个问题,那么我认为您在代码中构建了80000 * 80000数组。 即使您的输入只有一个字节,80000 * 80000b = 6400000000b = 5.9GB,也超出了.Net“单个对象2GB”的限制。

您应该将比较代码分成较小的部分,例如一次获取1000条记录,对它们进行比较,然后获得下一条1000条记录。

您遇到的问题很可能是由于您一次要获取大量记录。

您没有指定要比较的内容,也没有指定找到匹配项时应该做什么。

无论如何,我建议您使用Parallel LINQ扩展 他们认真地踢屁股,使百果馅从这种工作量中解脱出来,并且内置了许多智能功能,可以为工作选择最佳方法。

使用DataReader代替Dataset可以提高应用程序性能并减少系统开销。 这是由于一次将一行存储在内存中。 创建Command对象的实例后,可以通过调用Command.ExecuteReader来创建DataReader。 查看http://msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqldatareader.aspx

您不应该使用交叉联接。 最好将表一次加载到主存储器中,如下所示:

SqlCommand cmd 
= new SqlCommand("select g.goterm,g.gene from genematrix g ", con);
    SqlDataAdapter da = new SqlDataAdapter(cmd);
    DataSet ds = new DataSet();
    da.Fill(ds);

然后使用字典进行比较。 这是一些“空中代码”(未经测试,未经编译,就在我脑海中):

var d = new Dictionary<string, List<string>();
for each(var row in ds.Rows)
{
    string key = (string)row["goterm"];
    if(!d.ContainsKey(key))
        d.Add(key, new List<string>());
     d[key].Add((string)row["gene"]);
}

for each(var k in d.Keys)
{
     Console.Write(k + ": ");
     for each(var gene in d[k])
          Console.Write(gene + " ");
     Console.WriteLine();
}

(ALAS,如果这不只是开箱即用,它应该为您提供一个大概的解决方法)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM