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 ** 阅读(490) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 

导航

统计

公告

你好!

常用链接

留言簿(2)

随笔档案

文章分类

文章档案

新闻档案

相册

收藏夹

C#学习

友情链接

搜索

最新评论

阅读排行榜

评论排行榜