Oracle批量导入100万条数据不到1秒

前端之家收集整理的这篇文章主要介绍了Oracle批量导入100万条数据不到1秒前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

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

上一次文章中提及的试验: SqlServer批量导入C#100万条数据仅4秒附源码http://www.jb51.cc/article/p-faxczxmd-bpr.html

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

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

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

好了正文开始。

● 普通肉垫式

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

代码
  1. //
  2. 设置一个数据库的连接串,
  3. string
  4. connectStr
  5. =
  6. "
  7. User Id=scott;Password=tiger;Data Source=
  8. "
  9. ; OracleConnection conn
  10. =
  11. new
  12. OracleConnection(connectStr); OracleCommand command
  13. =
  14. new
  15. OracleCommand(); command.Connection
  16. =
  17. conn; conn.Open(); Stopwatch sw
  18. =
  19. new
  20. Stopwatch(); sw.Start();
  21. 通过循环写入大量的数据,这种方法显然是肉垫
  22. for
  23. (
  24. int
  25. i
  26. =
  27. 0
  28. ; i
  29. <
  30. recc; i
  31. ++
  32. ) {
  33. string
  34. sql
  35. =
  36. insert into dept values(
  37. "
  38. +
  39. i.ToString()
  40. +
  41. ,
  42. )
  43. "
  44. ; command.CommandText
  45. =
  46. sql; command.ExecuteNonQuery(); } sw.Stop(); System.Diagnostics.Debug.WriteLine(
  47. 普通插入:
  48. "
  49. +
  50. recc.ToString()
  51. +
  52. 所占时间:
  53. "
  54. +
  55. sw.ElapsedMilliseconds.ToString());

我们先准备好程序,但是先不做时间的测定,因为在后面我们会用多次循环的方式来计算所占用的时间。

● 使用ODP特性

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

  1. 设置一个数据库的连接串
  2. new
  3. OracleCommand(); command.Connection
  4. =
  5. conn;
  6. 到此为止,还都是我们熟悉的代码,下面就要开始喽
  7. 这个参数需要指定每次批插入的记录数
  8. command.ArrayBindCount
  9. =
  10. recc;
  11. 在这个命令行中,用到了参数,参数我们很熟悉,但是这个参数在传值的时候
  12. 用到的是数组,而不是单个的值,这就是它独特的地方
  13. command.CommandText
  14. =
  15. insert into dept values(:deptno,:deptname,:loc)
  16. "
  17. ; conn.Open();
  18. 下面定义几个数组,分别表示三个字段,数组的长度由参数直接给出
  19. int
  20. [] deptNo
  21. =
  22. new
  23. int
  24. [recc];
  25. string
  26. [] dname
  27. =
  28. string
  29. [recc];
  30. string
  31. [] loc
  32. =
  33. 为了传递参数,不可避免的要使用参数,下面会连续定义三个
  34. 名称可以直接看出每个参数的含义,不在每个解释了
  35. OracleParameter deptNoParam
  36. =
  37. new
  38. OracleParameter(
  39. deptno
  40. "
  41. ,OracleDbType.Int32); deptNoParam.Direction
  42. =
  43. ParameterDirection.Input; deptNoParam.Value
  44. =
  45. deptNo; command.Parameters.Add(deptNoParam); OracleParameter deptNameParam
  46. =
  47. deptname
  48. =
  49. ParameterDirection.Input; deptNameParam.Value
  50. =
  51. dname; command.Parameters.Add(deptNameParam); OracleParameter deptLocParam
  52. =
  53. loc
  54. =
  55. ParameterDirection.Input; deptLocParam.Value
  56. =
  57. loc; command.Parameters.Add(deptLocParam); Stopwatch sw
  58. =
  59. 在下面的循环中,先把数组定义好,而不是像上面那样直接生成sql
  60. 0
  61. ; i
  62. <
  63. recc; i
  64. ++
  65. ) { deptNo[i]
  66. =
  67. i; dname[i]
  68. =
  69. i.ToString(); loc[i]
  70. =
  71. i.ToString(); }
  72. 这个调用将把参数数组传进sql,同时写入数据库
  73. command.ExecuteNonQuery(); sw.Stop(); System.Diagnostics.Debug.WriteLine(
  74. 批量插入:
  75. "
  76. +
  77. sw.ElapsedMilliseconds.ToString());

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

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

  1. for
  2. (
  3. int
  4. i
  5. =
  6. 1
  7. ; i
  8. <=
  9. 50
  10. ; i
  11. ++
  12. ) { Truncate(); OrdinaryInsert(i
  13. *
  14. 1000
  15. ); Truncate(); BatchInsert(i
  16. *
  17. 1000
  18. ); }

猜你在找的Oracle相关文章