接受导入数据的表名是 CALLS新葡京32450网址:,Oracle 数据库的CALLS表中

发布时间:2020-04-25  栏目:数据  评论:0 Comments

每种数据库助理馆员都会直面数据导入的标题,那有恐怕产生在数据库的新老移植进程中,也许是在数据库崩溃后的复原重新建设布局进程中,还应该有极大希望是在成立测量试验数据库的依葫芦画瓢条件经过中,由此可以预知视作一名合格的数据库管理员,你应该加强选择种种数据导入诉求的技艺储备,同临时间还要尽可能满意人本能的对导入速度的苛求。本文仅针对
Oracle
数据库所提供的加快数据导入的种种特色和技巧扩充切磋,当中的有些办法也足以转正应用于任何数据库。以下七种多少导入方法哪个最适用须要针对具体意况具体解析,小编也顺便列举了影响导入速度的各样因素供切磋。为了比较种种数据导入方法的效用,作者创造了示例表和数据集,并用种种法子导入示例数据集来计算总体导入时间和导入进度占用
CPU 时间,这里得出的时刻仅供参照他事他说加以考察。供给证实的是,建议您利用 Oracle 9i
集团版数据库,当然你也足以尝尝运用 Oracle 7.3
以上的规范版数据库。本文使用的机器配置为:CPU AMD P4,内存256M,数据库 Oracle 9i 集团版。

示例表结会谈数据集

命名空间:Oracle.DataAccess.Client

示例表布局和数据集

为了演示和相比较各类数码导入方法,作者要是数据导入职分是将表面文件数量导入到
Oracle 数据库的CALLS表中,外界数据文件满含十万条呼叫中央记录,将近 6MB
的文件大小,具体的数据示举例下:

组件:Oracle.DataAccess.dll(2.112.1.0)

为了演示和比较种种数据导入方法,小编一旦数据导入职责是将表面文件数量导入到
Oracle 数据库的CALLS表中,外界数据文件富含十万条呼叫中央记录,将近 6MB
的文件大小,具体的数量示比如下:

82302284384,2000-04-18:13:18:58,5001,控诉,手提式有线电话机三包维修品质82302284385,二〇〇四-04-18:13:18:59,3352,咨询,供水热线的号子82302284386,二零零二-04-18:13:19:01,3142,提出,增设公交线路

ODP.NET 版本:ODP.NET for .NET Framework 2.0 或 ODP.NET for .NET
Framework 4

82302284384,二〇〇二-04-18:13:18:58,5001,投诉,手机三包维修品质82302284385,二零零四-04-18:13:18:59,3352,咨询,供水热线的数码82302284386,二零零四-04-18:13:19:01,3142,建议,增设公共交通线路

选拔导入数据的表名是 CALLS,表构造如下:

工具:Microsoft Visual Studio Ultimate 2013 + Oracle SQL Developer
1.5.5 + Oracle Database 11g Enterprise Edition 11.2.0.1.0(32位)
+ TNS for 32-bit Windows 11.2.0.1.0

接纳导入数据的表名是 CALLS,表构造如下:

Name Null? Type Comment———— ——— ————-
—————–CALL_ID NOT NULL NUMBER Primary keyCALL_DATE NOT NULL
DATE Non-unique indexEMP_ID NOT NULL NUMBERCALL_TYPE NOT NULL
VARCHAR2(12)DETAILS VARCHAR2(25)

 

Name Null? Type Comment———— ——— ————-
—————–CALL_ID NOT NULL NUMBER Primary keyCALL_DATE NOT NULL
DATE Non-unique indexEMP_ID NOT NULL NUMBERCALL_TYPE NOT NULL
VARCHAR2(12)DETAILS VARCHAR2(25)

各种数据插入INSERT

方式一:ArrayBind

当插入一条数据时,SQL 语句如下:

INSERT INTO table_name VALUES (:col1, :col2, :col3, :col4, :col5)

  1 public void InsertDataRow(Dictionary<string, object> dataRow)
  2 {
  3     StringBuilder sbCmdText = new StringBuilder();
  4     sbCmdText.AppendFormat("INSERT INTO {0}(", m_TableName);
  5     sbCmdText.Append(string.Join(",", dataRow.Keys.ToArray()));
  6     sbCmdText.Append(") VALUES (");
  7     sbCmdText.Append(":" + string.Join(",:", dataRow.Keys.ToArray()));
  8     sbCmdText.Append(")");
  9 
 10     using (OracleConnection conn = new OracleConnection())
 11     {
 12         using (OracleCommand cmd = conn.CreateCommand())
 13         {
 14             cmd.CommandType = CommandType.Text;
 15             cmd.CommandText = sbCmdText.ToString();
 16             OracleParameter parameter = null;
 17             OracleDbType dbType = OracleDbType.Object;
 18             foreach (string colName in dataRow.Keys)
 19             {
 20                 dbType = GetOracleDbType(dataRow[colName]);
 21                 parameter = new OracleParameter(colName, dbType);
 22                 parameter.Direction = ParameterDirection.Input;
 23                 parameter.OracleDbTypeEx = dbType;
 24                 parameter.Value = dataRow[colName];
 25                 cmd.Parameters.Add(parameter);
 26             }
 27             conn.Open();
 28             int result = cmd.ExecuteNonQuery();
 29         }
 30     }
 31 }

此刻,每三个 OracleParameter 的 Value 值都授予单个字段的
三个具体值,这种也是特别守旧的插入数据的点子。

Oracle V6 中 OCI 编制程序接口参与了数组接口性子。

当使用 ArrayBind 时,OraleParameter 的 Value 值则是给与单个字段的
二个数组,即多条数据的该字段组合成的三个数组。当时 Oracle 仅须求推行二次SQL
语句,就能够在内部存款和储蓄器中批量剖析并导入数据,减弱程序与数据库之间往来的操作,其独到之处便是多少导入的全体时间鲜明收缩,特别是经过占用
CPU 的年月。

若是数据源是 DataTable 类型,首先把 DataTable 数据源,转变到object[][] 类型,然后绑定 OracleParameter 的 Value
值为对应字段的三个 Object[] 数组就能够;参谋代码如下:

  1 /// <summary>
  2 /// 批量插入大数据量
  3 /// </summary>
  4 /// <param name="columnData">列名-列数据字典</param>
  5 /// <param name="dataCount">数据量</param>
  6 /// <returns>插入数据量</returns>
  7 public int InsertBigData(Dictionary<string, object> columnData, int dataCount)
  8 {
  9     int result = 0;
 10     if (columnData == null || columnData.Count < 1)
 11     {
 12         return result;
 13     }
 14     string[] colHeaders = columnData.Keys.ToArray();
 15     StringBuilder sbCmdText = new StringBuilder();
 16     if (columnData.Count > 0)
 17     {
 18         // 拼接INSERT的SQL语句
 19         sbCmdText.AppendFormat("INSERT INTO {0}(", m_TableName);
 20         sbCmdText.Append(string.Join(",", colHeaders));
 21         sbCmdText.Append(") VALUES (");
 22         sbCmdText.Append(m_ParameterPrefix + string.Join("," + m_ParameterPrefix, colHeaders));
 23         sbCmdText.Append(")");
 24         OracleConnection connection = null;
 25         try
 26         {
 27             connection = new OracleConnection(GetConnectionString());
 28             using (OracleCommand command = connection.CreateCommand())
 29             {
 30                 command.ArrayBindCount = dataCount;
 31                 command.BindByName = true;
 32                 command.CommandType = CommandType.Text;
 33                 command.CommandText = sbCmdText.ToString();
 34                 command.CommandTimeout = 1800;
 35                 OracleParameter parameter;
 36                 OracleDbType dbType = OracleDbType.Object;
 37                 foreach (string colName in colHeaders)
 38                 {
 39                     dbType = GetOracleDbType(columnData[colName]);
 40                     parameter = new OracleParameter(colName, dbType);
 41                     parameter.Direction = ParameterDirection.Input;
 42                     parameter.OracleDbTypeEx = dbType;
 43                     parameter.Value = columnData[colName];
 44                     command.Parameters.Add(parameter);
 45                 }
 46                 connection.Open();
 47                 OracleTransaction trans = connection.BeginTransaction();
 48                 try
 49                 {
 50                     command.Transaction = trans;
 51                     result = command.ExecuteNonQuery();
 52                     trans.Commit();
 53                 }
 54                 catch (Exception ex)
 55                 {
 56                     trans.Rollback();
 57                     throw ex;
 58                 }
 59             }
 60         }
 61         finally
 62         {
 63             if (connection != null)
 64             {
 65                 connection.Close();
 66                 connection.Dispose();
 67             }
 68             GC.Collect();
 69             GC.WaitForFullGCComplete();
 70         }
 71     }
 72     return result;
 73 }

新葡京32450网址 1新葡京32450网址 2

  1 /// <summary>
  2 /// 根据数据类型获取OracleDbType
  3 /// </summary>
  4 /// <param name="value">数据</param>
  5 /// <returns>数据的Oracle类型</returns>
  6 private static OracleDbType GetOracleDbType(object value)
  7 {
  8     OracleDbType dataType = OracleDbType.Object;
  9     if (value is string[])
 10     {
 11         dataType = OracleDbType.Varchar2;
 12     }
 13     else if (value is DateTime[])
 14     {
 15         dataType = OracleDbType.TimeStamp;
 16     }
 17     else if (value is int[] || value is short[])
 18     {
 19         dataType = OracleDbType.Int32;
 20     }
 21     else if (value is long[])
 22     {
 23         dataType = OracleDbType.Int64;
 24     }
 25     else if (value is decimal[] || value is double[] || value is float[])
 26     {
 27         dataType = OracleDbType.Decimal;
 28     }
 29     else if (value is Guid[])
 30     {
 31         dataType = OracleDbType.Varchar2;
 32     }
 33     else if (value is bool[] || value is Boolean[])
 34     {
 35         dataType = OracleDbType.Byte;
 36     }
 37     else if (value is byte[])
 38     {
 39         dataType = OracleDbType.Blob;
 40     }
 41     else if (value is char[])
 42     {
 43         dataType = OracleDbType.Char;
 44     }
 45     return dataType;
 46 }

GetOracleDbType

说明:如若运用分次(每一趟1万数据)实践 InsertBigData
方法,速度反倒比叁次性实行 InsertBigData 方法慢,详见上面测验结果;

测量试验结果:

无索引,数据类型:4列NVARCHAR2,2列NUMBER

30+万(7.36M):三次性导入用时 15:623,每一趟10000导入用时

60+万(14.6M):二遍性导入用时 28:207,每趟10000导入用时 1:2:300

100+万(24.9M):壹回性导入报如下卓殊

新葡京32450网址 3

这时候实际上从能源监视器上得以查出仍然有可用内部存款和储蓄器,不过依然报
OutOfMemoryException,所以猜疑应该是三个 bug;

假诺老是10000导入用时 2:9:252

如若老是50000导入用时 58:101

外加 InsertBigData 方法应用示例:

新葡京32450网址 4新葡京32450网址 5

  1 // 每10000数据导入一次
  2 Dictionary<string, object> columnsData = new Dictionary<string, object>();
  3 int dataCount = m_SourceDataTable.Rows.Count;
  4 int times = dataCount / 10000 + (dataCount % 10000 == 0 ? 0 : 1);
  5 for (int i = 0; i < times; i++)
  6 {
  7     int startIndex = i * 10000;
  8     int endIndex = (i + 1) * 10000;
  9     endIndex = endIndex > dataCount ? dataCount : endIndex;
 10     int currDataCount = endIndex - startIndex;
 11     columnsData.Add("COL1", new string[currDataCount]);
 12     columnsData.Add("COL2", new string[currDataCount]);
 13     columnsData.Add("COL3", new decimal[currDataCount]);
 14     columnsData.Add("COL4", new string[currDataCount]);
 15     columnsData.Add("COL5", new decimal[currDataCount]);
 16     columnsData.Add("COL6", new string[currDataCount]);
 17     for (int rowIndex = startIndex; rowIndex < endIndex; rowIndex++)
 18     {
 19         int dicRowIndex = rowIndex - startIndex;// 列数据行索引
 20         foreach (string colName in columnsData.Keys)
 21         {
 22             object cell = m_SourceDataTable.Rows[rowIndex][colName];
 23             string cellStr = (cell + "").TrimEnd(new char[] { '\0', ' ' });
 24             if (colName == "COL3" || colName == "COL5")
 25             {
 26                 decimal value = 0;
 27                 decimal.TryParse(cellStr, out value);
 28                 ((decimal[])columnsData[colName])[dicRowIndex] = value;
 29             }
 30             else
 31             {
 32                 ((string[])columnsData[colName])[dicRowIndex] = cellStr;
 33             }
 34         }
 35     }
 36     m_DAL.InsertBigData(columnsData, currDataCount);
 37 
 38     columnsData.Clear();
 39     GC.Collect();
 40     GC.WaitForFullGCComplete();
 41 }

View Code

留下评论

网站地图xml地图