System.OutOfMemoryException 發生的兩種情況
1)應用程序消耗了過多的內存
2)內存碎片過多
故障解決:
a)增加w3wp進程可以使用的內存空間
打開boot.ini的 /3GB開關
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)\WINNT
[operating systems]multi(0)disk(0)rdisk(0)partition(2)\WINNT="????" /3GB
B)減少內存分配,避免內存碎片的出現
修改DAO基類,將dataset的RemotingFormat ,
設為SerializationFormat.Binary
我用C#做數據庫應用的時候,經常遇到的一個問題就是內存消耗特別大。這種情
況在作大數據量的數據庫導入導出的時候更為明顯。
說一個常見的數據庫導入導出的Case, 大家看看比較合理的辦法是什么:
環境:
有一個數據庫SRC, 里面有500萬條記錄。有A, B, C三個字段。數據庫的大小去掉水分后,大約500MB的數量級。這個作為源數據庫。數據庫DEST是目標數據庫,里面有AA, BB, CC, DD, EE, FF等5個字段。其中,AA, BB, CC的值,是根據SRC.A和B的值計算得來的。而且過程復雜,所以不適合使用存儲過程實現。并且AA, BB, CC不是單獨得出,而是同時以SRC.A和SRC.B得出的(當然,運算三遍可以分別取到各值,但顯然運算量就大了3倍)。目的:
將SRC中的所有數據經過變換,導入到數據庫DEST中。我所嘗試過的方法:
1. 最開始用最簡單的DataAdapter.Fill(DataTable)的辦法。
然后
foreach(DataRow rowsrc in dtSrc){
DataRow row = dtDest.NewRow();
....
dtDest.Rows.Add(row);
}
daDest.Update(dtDest);
dtDest.AcceptChanges();
這明顯不是處理大數據量遷移的辦法。
最明顯的問題是內存消耗極大。500MB的數據庫表變成DataSet中的DataTable,
體積括大了很多。再加上dtDest中的拷貝,還有daDest.Update所占用的資源,
很容易就超過了2GB的應用程序內存地址空間,而報錯退出了。
2. 我嘗試用DataReader讀入數據,然后寫進dtDest
using( ... reader = ...){
while(reader.Read()){
DataRow row = dtDest.NewRow();
....
dtDest.Rows.Add(row);
}
}
daDest.Update(dtDest);
dtDest.AcceptChanges();內存占用少了很多,因為SRC讀入DataReader的數據,似乎會因為之后不用了,
而有所釋放。但是已經進入dtDest的數據沒有必要存儲在內存中的道理。可是又
沒有辦法。即使daDest.Update和dtDest.AcceptChanges()后,它依然占用這內
存。因此將daDest.Update和dtDest.AcceptChanges()放入循環內,并不能對內
存使用有所改善。
3. 純SQL語句。不用DataTable
用SqlCommand.ExecuteNonQuery()的來執行"Insert Into ..."的SQL語句。這樣
作后,發現內存占用大大降低了。起到了想達到的“管道”的效果。可是最之而來
的確實更嚴重的問題。這樣做的磁盤空間占用極大。數據庫會產生大量的日志,
和廢棄空間。以Access為例,程序運行一段時間后,就超過了2GB最大文件的限
制。當執行“壓縮和恢復數據庫”后,只有100MB左右。可見產生的數據垃圾多
大。當然,采用SQL Server會沒有2GB的限制,但是這么大量的日志和廢棄空
間,絕對不是一個適合的結果。而且,如果安這種比例,一個500MB的數據庫,
將占用超過10GB的存儲空間,這是一個太大的浪費了。當然事后可以壓縮,但是
處理過程中的空間浪費不容忽視。
4. 不輸出到數據庫,以CSV輸出到文本文件
這是個辦法,至少一來不占用什么內存,二來,也沒有浪費硬盤空間。但是麻煩
的是,丟失了最重要的類型信息。對于字符串和數字還好說,最多就是字符串沒
有了長度,數字沒有了精度,但都還能夠保存下來。比較麻煩的是有些復雜類
型,比如IMAGE, Binary,和GUID等,這種字節流形式的類型是沒有辦法報存在
CSV中的。
5.導出到XML
當然用XML好一些,但是其Binary存儲的Parse也是很耗費資源的,而且,用XML
如何才能導入到數據庫中呢?用C#就又回到老路上來了。SQL Server支持XML,
但是其他的數據庫呢?例如Access? 畢竟不是所有人都買的起SQL Server或者所
有場合都適于使用SQL Server的。
對于這個問題大家有什么好辦法么?我覺得操作大一點的數據庫的時候,內存占
用是個很明顯的問題。也許有很簡單的方法我沒有考慮到而走了很多彎路。謝謝了。