| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 16643 人关注过本帖, 19 人收藏
标题:C# 海量数据瞬间插入到数据库的方法
只看楼主 加入收藏
bygg
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:乖乖的心中
等 级:版主
威 望:241
帖 子:13555
专家分:3076
注 册:2006-10-23
结帖率:93.75%
收藏(19)
 问题点数:0 回复次数:58 
C# 海量数据瞬间插入到数据库的方法
当我们在数据库中进行大量的数据追加时,是不是经常因为数据量过大而苦恼呢?
而所谓的海量数据,一般也是上万级的数据,比如我们要添加一百万条数据,应该如何提高它的效率呢?

Oracle数据库:

普通肉垫式

    什么叫批量插入呢,就是一次性插入一批数据,我们可以把这批数据理解为一个大的数组,而这些全部只通过一个SQL来实现,而在传统方式下,需要调用很多次的SQL才可以完成,这就是著名的“数组绑定”的功能。我们先来看一下传统方式下,插入多行记录的操作方式:
程序代码:
//设置一个数据库的连接串,
string connectStr = "User Id=scott;Password=tiger;Data Source=";
OracleConnection conn = new OracleConnection(connectStr);
OracleCommand command = new OracleCommand();
command.Connection = conn;
conn.Open();
//通过循环写入大量的数据,这种方法显然是肉垫
for (int i = 0; i < recc; i++)
{
    string sql = "insert into dept values(" + i.ToString() + "," + i.ToString() + "," + i.ToString() + ")";
     = sql;
    command.ExecuteNonQuery();
} 

使用ODP特性
程序代码:
//设置一个数据库的连接串
string connectStr = "User Id=scott;Password=tiger;Data Source=";
OracleConnection conn = new OracleConnection(connectStr);
OracleCommand command = new OracleCommand();
command.Connection = conn;
//到此为止,还都是我们熟悉的代码,下面就要开始喽
//这个参数需要指定每次批插入的记录数
command.ArrayBindCount = recc;
//在这个命令行中,用到了参数,参数我们很熟悉,但是这个参数在传值的时候
//用到的是数组,而不是单个的值,这就是它独特的地方
 = "insert into dept values(:deptno, :deptname, :loc)";
conn.Open();
//下面定义几个数组,分别表示三个字段,数组的长度由参数直接给出
int[] deptNo = new int[recc];
string[] dname = new string[recc];
string[] loc = new string[recc];
// 为了传递参数,不可避免的要使用参数,下面会连续定义三个
// 从名称可以直接看出每个参数的含义,不在每个解释了
OracleParameter deptNoParam = new OracleParameter("deptno", OracleDbType.Int32);
deptNoParam.Direction = ParameterDirection.Input;
deptNoParam.Value = deptNo;
command.Parameters.Add(deptNoParam);

 OracleParameter deptNameParam = new OracleParameter("deptname", OracleDbType.Varchar2);
deptNameParam.Direction = ParameterDirection.Input;
deptNameParam.Value = dname; command.Parameters.Add(deptNameParam);
OracleParameter deptLocParam = new OracleParameter("loc", OracleDbType.Varchar2);
deptLocParam.Direction = ParameterDirection.Input;
deptLocParam.Value = loc;
command.Parameters.Add(deptLocParam);
//在下面的循环中,先把数组定义好,而不是像上面那样直接生成SQL
for (int i = 0; i < recc; i++)
{
    deptNo[i] = i;
    dname[i] = i.ToString();
    loc[i] = i.ToString();
}
//这个调用将把参数数组传进SQL,同时写入数据库
command.ExecuteNonQuery();


好了,到目前为止,两种方式的插入操作程序已经完成,就剩下对比了。我在主函数处写了一个小函数,循环多次对两个方法进行调用,并且同时记录下时间,对比函数如下:
程序代码:
for (int i = 1; i <= 50; i++)
{
    OrdinaryInsert(i * 1000); 

    BatchInsert(i * 1000);
} 

当数据量达到100万级别时,所用时间依然令人满意,最快一次达到890毫秒,一般为1秒左右。

    经过试验,得出一组数据,可以看出两种方式在效率方面惊人的差距(占用时间的单位为毫秒),部分数据如下:
图片附件: 游客没有浏览图片的权限,请 登录注册

看一下由此数据生成的散点图:
图片附件: 游客没有浏览图片的权限,请 登录注册


 其中有些数据有些跳跃,可能和数据库本身有关系,但是大部分数据已经能说明问题了。看了这些数据后,是不是有些心动了?

SqlServer数据库

既然Oracle可以如此爽快,那么在SqlServer中是否也可以这样做呢?
但是在SqlServer中却没有诸如ArrayBindCount 这样的操作属性。
不过,我们却可以借助于BULK INSERT来进入海量数据的添加。
代码:
程序代码:
//设置一个数据库的连接串
            string connectStr = "……";
            SqlConnection conn = new SqlConnection(connectStr);
            SqlCommand command = new SqlCommand();
             = 0;
            command.Connection = conn;
            /*说明:
             * “c:\\sql.txt”是一个预先生成的包含100条数据的文件
             * 每一个字段的信息以“,”分割
             * 每一条数据以“|”符号分隔
             * 每10万条数据一个事务。
             */
             = "BULK INSERT TableB FROM 'c:\\sql.txt' WITH (FIELDTERMINATOR = ',',ROWTERMINATOR ='|',BATCHSIZE = 100000)";
            conn.Open();
            //System.Data.SqlClient.SqlBulkCopy sqlBC
            command.ExecuteNonQuery();

            conn.Close();

虽然比不上Oracle那么变态,但是插入百万条数据也不过只用了几秒时间,比起我们平时的添加速度,无疑已经让人非常兴奋了吧,呵呵。

大家还不快试试去?

收到的鲜花
  • gameohyes2010-09-29 11:09 送鲜花  49朵   附言:好文章.辛苦了
  • zhoufeng19882010-09-30 13:37 送鲜花  49朵   附言:好文章
  • wangnannan2010-11-05 15:44 送鲜花  49朵   附言:好文章
  • guang2010-11-06 17:51 送鲜花  5朵   附言:很好,支持!
搜索更多相关主题的帖子: 数据库 海量 
2010-09-28 14:44
zwk199024
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:63
专家分:102
注 册:2010-9-15
收藏
得分:0 
很好!很强大!学习了
2010-09-28 15:28
ttkyw
Rank: 1
等 级:新手上路
帖 子:9
专家分:0
注 册:2008-12-19
收藏
得分:0 
不错,
2010-09-29 10:14
gameohyes
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:湖南
等 级:版主
威 望:53
帖 子:1275
专家分:3629
注 册:2009-3-5
收藏
得分:0 
无条件支持...

C#超级群 74862681,欢迎大家的到来!
2010-09-29 10:23
bygg
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:乖乖的心中
等 级:版主
威 望:241
帖 子:13555
专家分:3076
注 册:2006-10-23
收藏
得分:0 
支持就得给我加分,哈哈

飘过~~
2010-09-29 11:04
gameohyes
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:湖南
等 级:版主
威 望:53
帖 子:1275
专家分:3629
注 册:2009-3-5
收藏
得分:0 
原来还可以+分哈.真的很少用
收到的鲜花
  • bygg2010-09-29 11:41 送鲜花  1朵  
  • bygg2010-09-29 11:42 送鲜花  1朵  
  • bygg2010-09-29 11:42 送鲜花  1朵  
  • bygg2010-09-29 11:42 送鲜花  1朵  
  • bygg2010-09-29 11:43 送鲜花  1朵  

C#超级群 74862681,欢迎大家的到来!
2010-09-29 11:10
bygg
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:乖乖的心中
等 级:版主
威 望:241
帖 子:13555
专家分:3076
注 册:2006-10-23
收藏
得分:0 
现在知道了吧,以后多加点,哈哈

飘过~~
2010-09-29 11:41
qindh
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2010-8-12
收藏
得分:0 
学习了,以前虽有这种想法,但不知如何实现。
2010-09-29 17:35
zhoufeng1988
Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15
来 自:北京
等 级:贵宾
威 望:27
帖 子:1432
专家分:6329
注 册:2009-5-31
收藏
得分:0 
原来你叫bygg。。。
.
谢谢分享,给你加分了~哈哈
2010-09-30 13:37
bygg
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:乖乖的心中
等 级:版主
威 望:241
帖 子:13555
专家分:3076
注 册:2006-10-23
收藏
得分:0 
看来zhoufeng1988的眼睛不好使,呵呵

飘过~~
2010-09-30 14:03
快速回复:C# 海量数据瞬间插入到数据库的方法
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.051291 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved