Hopes

          Start Here..

           

          C#的數據庫應用如何解決內存消耗太大的問題呢?

          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的。

          對于這個問題大家有什么好辦法么?我覺得操作大一點的數據庫的時候,內存占
          用是個很明顯的問題。也許有很簡單的方法我沒有考慮到而走了很多彎路。謝謝了。

          posted on 2012-12-15 09:36 ** 閱讀(497) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          統計

          公告

          你好!

          常用鏈接

          留言簿(2)

          隨筆檔案

          文章分類

          文章檔案

          新聞檔案

          相冊

          收藏夾

          C#學習

          友情鏈接

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 泾源县| 巴彦县| 自治县| 亚东县| 汽车| 阳东县| 汪清县| 浦城县| 四会市| 辽源市| 莱西市| 惠东县| 永城市| 沁阳市| 乐业县| 安阳市| 太湖县| 霍林郭勒市| 青神县| 九龙坡区| 大埔县| 呼和浩特市| 牙克石市| 长汀县| 甘孜| 从化市| 盖州市| 龙川县| 民丰县| 玉树县| 武城县| 萨迦县| 青冈县| 宁德市| 南江县| 凤庆县| 塔河县| 鄂托克旗| 扶余县| 阜阳市| 开原市|