我对Oracle很新,但我在其他几个应用程序上使用了Bulk insert。大多数人似乎更快地使用它,但我有一对夫妇在减慢应用程序的速度。这是我的第二个,它显着减慢了它,所以我想知道我是否有不正确的设置或者我需要以不同的方式设置它。在这种情况下,我有一个处理~1900条记录的控制台应用程序。单独插入它需要大约2.5小时,当我切换到批量插入时,它跳跃到5小时。
我所依据的文章是http://www.oracle.com/technetwork/issue-archive/2009/09-sep/o59odpnet-085168.html
以下是我正在做的事情,我从数据库中检索一些记录,进行计算,然后将结果写入文本文件。完成计算后,我必须将这些结果写回数据库中的不同表,以便我们可以在需要时回顾以后的计算结果。
当我进行计算时,我将结果添加到List中。一旦我完成了写出文件,我会查看该列表,如果有任何记录,我会进行批量插入。
使用批量插入,我在App.config中有一个设置来设置我想要插入的记录数。在这种情况下,我使用了250条记录。我认为最好将内存数组限制为250条记录而不是1,900条。我将该列表循环到App.config中的计数,并为每列创建一个数组。然后将这些数组作为参数传递给Oracle。
的App.config
<add key="UpdateBatchCount" value="250" />
类
class EligibleHours
{
public string EmployeeID { get; set; }
public decimal Hours { get; set; }
public string HoursSource { get; set; }
}
数据管理器
public static void SaveEligibleHours(List<EligibleHours> listHours)
{
//set the number of records to update batch on from config file Subtract one because of 0 based index
int batchCount = int.Parse(ConfigurationManager.AppSettings["UpdateBatchCount"]);
//create the arrays to add values to
string[] arrEmployeeId = new string[batchCount];
decimal[] arrHours = new decimal[batchCount];
string[] arrHoursSource = new string[batchCount];
int i = 0;
foreach (var item in listHours)
{
//Create an array of employee numbers that will be used for a batch update.
//update after every X amount of records, update. Add 1 to i to compensated for 0 based indexing.
if (i + 1 <= batchCount)
{
arrEmployeeId[i] = item.EmployeeID;
arrHours[i] = item.Hours;
arrHoursSource[i] = item.HoursSource;
i++;
}
else
{
UpdateDbWithEligibleHours(arrEmployeeId, arrHours, arrHoursSource);
//reset counter and array
i = 0;
arrEmployeeId = new string[batchCount];
arrHours = new decimal[batchCount];
arrHoursSource = new string[batchCount];
}
}
//process last array
if (arrEmployeeId.Length > 0)
{
UpdateDbWithEligibleHours(arrEmployeeId, arrHours, arrHoursSource);
}
}
private static void UpdateDbWithEligibleHours(string[] arrEmployeeId, decimal[] arrHours, string[] arrHoursSource)
{
StringBuilder sbQuery = new StringBuilder();
sbQuery.Append("insert into ELIGIBLE_HOURS ");
sbQuery.Append("(EMP_ID, HOURS_SOURCE, TOT_ELIG_HRS, REPORT_DATE) ");
sbQuery.Append("values ");
sbQuery.Append("(:1, :2, :3, SYSDATE) ");
string connectionString = ConfigurationManager.ConnectionStrings["Server_Connection"].ToString();
using (OracleConnection dbConn = new OracleConnection(connectionString))
{
dbConn.Open();
//create Oracle parameters and pass arrays of data
OracleParameter p_employee_id = new OracleParameter();
p_employee_id.OracleDbType = OracleDbType.Char;
p_employee_id.Value = arrEmployeeId;
OracleParameter p_hoursSource = new OracleParameter();
p_hoursSource.OracleDbType = OracleDbType.Char;
p_hoursSource.Value = arrHoursSource;
OracleParameter p_hours = new OracleParameter();
p_hours.OracleDbType = OracleDbType.Decimal;
p_hours.Value = arrHours;
OracleCommand objCmd = dbConn.CreateCommand();
objCmd.CommandText = sbQuery.ToString();
objCmd.ArrayBindCount = arrEmployeeId.Length;
objCmd.Parameters.Add(p_employee_id);
objCmd.Parameters.Add(p_hoursSource);
objCmd.Parameters.Add(p_hours);
objCmd.ExecuteNonQuery();
}
}