[英]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.