C#中利用ODP实现瞬间导入百万级数据详解

摘要:
.NET程序中可以通过ODP调用特性,对Oracle数据库进行操作,今天来讲一下数据批量插入的功能,所用技术不高不深,相信很多朋友都接触过,小弟班门弄斧了,呵呵。实验目的在于挖掘、对比宿主程序中的数据批量操作方法。

.NET程序中可以通过ODP调用特性,对Oracle数据库进行操作,今天来讲一下数据批量插入的功能,所用技术不高不深,相信很多朋友都接触过,小弟班门弄斧了,呵呵。这篇文章是上篇文章的续集,因为上一次试验的征集结果没有突破4秒的方法,所以这次继续挑战与挖掘新方法,虽然是Oracle,但仍具有一定收藏意义。

这个试验是针对SQL SERVER数据库的,宿主环境也是.NET,有兴趣的朋友可以将这两个试验对比一下,为日后工作批量导数提供支持。

另外,一些朋友对上次试验环境有些异议,认为应该对数据库和服务器做优化或设置,以体现试验最终的时间结果。这个固然会影响试验的时间结果,但考虑到在试验环境中,对数据库优化的标准与优化程度不便统一与定量,试验结果也不易说明其影响源,所以这次试验依然以标准数据库建库后的配置为主,试验所在服务器硬件环境与上次试验保持一致。实验目的在于挖掘、对比宿主程序中的数据批量操作方法。

有新方法提升性能时间指标的朋友,欢迎互相切磋,互相提高,嘴上功夫就免了。。。

好了正文开始。

普通肉垫式

什么叫批量插入呢,就是一次性插入一批数据,我们可以把这批数据理解为一个大的数组,而这些全部只通过一个SQL来实现,而在传统方式下,需要调用很多次的SQL才可以完成,这就是著名的“数组绑定”的功能。我们先来看一下传统方式下,插入多行记录的操作方式:

//设置一个数据库的连接串,
stringconnectStr ="User Id=scott;Password=tiger;Data Source=";
OracleConnection conn
=newOracleConnection(connectStr);
OracleCommand command
=newOracleCommand();
command.Connection
=conn; conn.Open();
Stopwatch sw
=newStopwatch();
sw.Start();
//通过循环写入大量的数据,这种方法显然是肉垫
for(inti =0; i <recc; i++)
{
stringsql ="insert into dept values("+i.ToString() +","+i.ToString() +","+i.ToString() +")";
command.CommandText
=sql; command.ExecuteNonQuery();
}
sw.Stop();
System.Diagnostics.Debug.WriteLine(
"普通插入:"+recc.ToString() +"所占时间:"+sw.ElapsedMilliseconds.ToString());
我们先准备好程序,但是先不做时间的测定,因为在后面我们会用多次循环的方式来计算所占用的时间。

● 使用ODP特性

看上面的程序,大家都很熟悉,因为它没有用到任何ODP的特性,而紧接着我们就要来介绍一个神奇的程序了,我们看一下代码,为了更直观,我把所有的注释及说明直接写在代码里:


//设置一个数据库的连接串
stringconnectStr ="User Id=scott;Password=tiger;Data Source=";
OracleConnection conn
=newOracleConnection(connectStr);
OracleCommand command
=newOracleCommand();
command.Connection
=conn;
//到此为止,还都是我们熟悉的代码,下面就要开始喽
//这个参数需要指定每次批插入的记录数
command.ArrayBindCount =recc;
//在这个命令行中,用到了参数,参数我们很熟悉,但是这个参数在传值的时候
//用到的是数组,而不是单个的值,这就是它独特的地方
command.CommandText ="insert into dept values(:deptno, :deptname, :loc)";
conn.Open();
//下面定义几个数组,分别表示三个字段,数组的长度由参数直接给出
int[] deptNo =newint[recc];
string[] dname =newstring[recc];
string[] loc =newstring[recc];
//为了传递参数,不可避免的要使用参数,下面会连续定义三个
//从名称可以直接看出每个参数的含义,不在每个解释了
OracleParameter deptNoParam =newOracleParameter("deptno", OracleDbType.Int32);
deptNoParam.Direction
=ParameterDirection.Input;
deptNoParam.Value
=deptNo; command.Parameters.Add(deptNoParam);
OracleParameter deptNameParam
=newOracleParameter("deptname", OracleDbType.Varchar2);
deptNameParam.Direction
=ParameterDirection.Input;
deptNameParam.Value
=dname; command.Parameters.Add(deptNameParam);
OracleParameter deptLocParam
=newOracleParameter("loc", OracleDbType.Varchar2);
deptLocParam.Direction
=ParameterDirection.Input;
deptLocParam.Value
=loc;
command.Parameters.Add(deptLocParam);
Stopwatch sw
=newStopwatch(); sw.Start();
//在下面的循环中,先把数组定义好,而不是像上面那样直接生成SQL
for(inti =0; i <recc; i++)
{
deptNo[i]
=i; dname[i] =i.ToString(); loc[i] =i.ToString();
}
//这个调用将把参数数组传进SQL,同时写入数据库
command.ExecuteNonQuery();
sw.Stop();
System.Diagnostics.Debug.WriteLine(
"批量插入:"+recc.ToString() +"所占时间:"+sw.ElapsedMilliseconds.ToString());

以上代码略显冗长,但是加上注释后基本也就表达清楚了。

好了,到目前为止,两种方式的插入操作程序已经完成,就剩下对比了。我在主函数处写了一个小函数,循环多次对两个方法进行调用,并且同时记录下时间,对比函数如下:

for(inti =1; i <=50; i++)
{
Truncate();
OrdinaryInsert(i
*1000);
Truncate();
BatchInsert(i
*1000);
}

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

经过试验,得出一组数据,可以看出两种方式在效率方面惊人的差距(占用时间的单位为毫秒),部分数据如下:

记录数

标准

批处理

1000

1545

29

2000

3514

20

3000

3749

113

4000

5737

40

5000

6820

52

6000

9469

72

7000

10226

69

8000

15280

123

9000

11475

83

10000

14536

121

11000

15705

130

12000

16548

145

13000

18765

125

14000

20393

116

15000

22181

159

因为篇幅原因,不再粘贴全部的数据,但是我们可以看一下由此数据生成的散点图:

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

源程序放了一段时间直接拷贝贴过来了,可能需要调试一下才能跑通,不过不是本质性问题,对了如果要测试别忘记安装Oracle访问组件。

本文是抄别人的BLOG,经本人亲测试,

5000 160毫秒

100000 2秒

1000000 41秒 用TOAD DELETE需要1分11秒

INSERT仍神速也!!!!

免责声明:文章转载自《C#中利用ODP实现瞬间导入百万级数据详解》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JavaScript能访问客户SQL数据库?能!(镜头主要参数工业相机镜头的参数与选型下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

如何打造高性能大数据分析平台

1.大数据是什么? 大数据是最近IT界最常用的术语之一。然而对大数据的定义也不尽相同,所有已知的论点例如结构化的和非结构化、大规模的数据等等都不够完整。大数据系统通常被认为具有数据的五个主要特征,通常称为数据的5 Vs。分别是大规模,多样性,高效性、准确性和价值性。 据Gartner称,大规模可以被定义为“在本(地)机数据采集和处理技术能力不足以为用户带来...

PostGIS数据库导入SHP数据

1 - 通过QGIS数据库管理工具将shp导入到postgis数据库 选择数据源中postgis对应的数据库schema(架构),然后选择导入图层或文件,弹出导入矢量图层面板。 关于选项的说明: 1) 源空间参考与目标空间参考无特殊需要,应当与数据源保持一致 2) 编码默认即可,不进行选择,如选择编码UTF-8,会导致中文乱码。 3) 需要注意源shp...

MSSQL为单独数据库创建登录账户

如果要为一个数据库创建一个独立的账号需要这个数据库为包含数据库 当前(非包含)的数据库所面临的问题在描述什么是包含数据库之前,先了解一下为什么会出现包含数据库。当前的数据库有一些问题,如下:1、在数据库迁移或部署的过程中一些信息会丢失     当我们将数据库从一个SQL Server实例迁移到另一个实例是,诸如登陆、工作代理等信息将不能一起被迁移。因为这...

关于oracle 数据库效率的优化

最近项目快要快要结束了,我们最终还是要面对我们一直存在的问题,就是数据库查询编码的问题,但是通过各个方面观察我们发现数据库仅仅200w条数据查询议一天的数据也就仅仅不到两万条数据没结果查了将近两分钟,这按章正常状态来讲那是不可能出现的情况,但是经过很久的观察我们还是找到了原因,那就是我们在做sql语句编写的时候那是不合理的 接下来我就给大家罗列一下相关情况...

使用PowerDesign15反向生成数据库

在Pd15中建立物理模型后,可以通过反向工程直接生成数据库的表结构。主要有以下几个步骤: 1、 首先设置一下数据库配置,选择对应要使用的数据库(此处选择Sql Server 2008 R2) 2、 配置数据库连接 3、 选择新建一个连接 4、 点击添加按钮 5、 选择Sql Server 6、 输入连接的名称以及数据库服务器地址 7、 选择...

mysql基本认识【关系型数据库和nosql、mysql操作流程和体系,库操作,表操作,数据的操作,字符集的操作,以及php作为client操作数据库】对连接本身没有疑问

1.关系型数据库永久性保存数据的仓库php的变量只是php脚本执行期间,临时性保存变量的空间【使用内存空间临时保存】 关系型数据库:利用二者的关系来描述实体的信息。【利用二维表字段名和字段值来进行描述】【关系型数据库根本不是可以使用外键将两个表构建成关联的意思,而是实现描述实体的二维表的形式】 nosql:not only sql【sql表示操作关系型数据...