簡體   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