通过存储过程进行Oracle大容量插入.花了太多时间

本文关键字:插入 太多 时间 大容量 Oracle 存储过程 | 更新日期: 2023-09-27 18:24:37

我正在尝试从c#代码到oracle数据库的高效批量插入/更新。如果我是通过声明来完成的,那么就不需要太多时间。

我正在使用ODP.NET目前,通过以下存储过程插入6000条记录需要15分钟。我必须使用这个存储的proc,因为它会生成唯一的user_id。

这个进程正在进行自动提交吗?有没有我应该关闭的自动提交设置?

请提出有效的方法。

 CREATE OR REPLACE
PROCEDURE sbx_staging_insert_user(client       IN varchar2,
                    username     IN varchar2,
                    comm_type    IN varchar2,
                    email_addr   IN varchar2,
                    buddy_name   IN varchar2,
                    --default_flag IN char,
                    user_id      OUT INT)
AS
BEGIN
select sbx_staging_user_id_seq.nextval into user_id from dual;
insert into sbx_staging_user
  (user_id,
   client,
   username,
   comm_type,
   email_addr,
   buddy_name,
   default_flag)
values
  (user_id,
   client,
   username,
   comm_type,
   email_addr,
   buddy_name,
  'Y');
   end sbx_staging_insert_user;

且C#代码为:

  cmd.Transaction = conn.BeginTransaction();
                        cmd.CommandType = CommandType.Text;
                        cmd.CommandText = "sbx_staging_insert_user";
                        cmd.CommandType = CommandType.StoredProcedure;
                        var userClientParam = new OracleParameter(":client", OracleDbType.Varchar2);
                        var usernameParam = new OracleParameter(":username", OracleDbType.Varchar2);
                        var commTypeParam = new OracleParameter(":comm_type", OracleDbType.Varchar2);
                        var defaultParam = new OracleParameter(":default_flag", OracleDbType.Char) { Size = 1};
                        var emailParam = new OracleParameter(":email_addr", OracleDbType.Varchar2) { IsNullable = true };
                        var buddyParam = new OracleParameter(":buddy_name", OracleDbType.Varchar2) { IsNullable = true };
                        var userIdParam = new OracleParameter(":user_id", OracleDbType.Int32) { Direction = ParameterDirection.Output };
                        cmd.Parameters.Add(userClientParam);
                        cmd.Parameters.Add(usernameParam);
                        cmd.Parameters.Add(commTypeParam);
                        //cmd.Parameters.Add(defaultParam);
                        cmd.Parameters.Add(emailParam);
                        cmd.Parameters.Add(buddyParam);
                        cmd.Parameters.Add(userIdParam);
                        var cuList = new List<string>(Users.Count);
                        var uList = new List<string>(Users.Count);
                        var ctList = new List<string>(Users.Count);
                        var dfList = new List<char>(Users.Count);
                        var eaList = new List<string>(Users.Count);
                        var bnList = new List<string>(Users.Count);
                        var uiList = new List<decimal>(Users.Count);
                        int loopCnt = 0;
                        foreach (var ud in Users)
                        {
                            cuList.Add(ud.User.Client);
                            uList.Add(ud.User.Username);
                            ctList.Add(ud.User.CommType);
                            dfList.Add(ud.User.Default ? 'Y' : 'N');
                            eaList.Add(ud.User.Email);
                            bnList.Add(ud.User.BuddyName);
                            uiList.Add(-1);
                        }
                        userClientParam.Value = cuList.ToArray();
                        usernameParam.Value = uList.ToArray();
                        commTypeParam.Value = ctList.ToArray();
                        //defaultParam.Value = dfList.ToArray();
                        emailParam.Value = eaList.ToArray();
                        buddyParam.Value = bnList.ToArray();
                        userIdParam.Value = uiList.ToArray();
                        cmd.ArrayBindCount = cuList.Count;//Users.Count;//
                        cmd.ExecuteNonQuery();
                        cmd.Transaction.Commit();

通过存储过程进行Oracle大容量插入.花了太多时间

试试这样的东西(未经测试,为简洁起见缩短):

public void insertRows()
{
 if (Users.Count > 0)
 {
  OracleTransaction trans=_conn.BeginTransaction();
  try
  {
   // create insert statement with bind vars
   Stringbuilder sb = new Stringbuilder();
   sb.Append("INSERT into sbx_staging_user(");
   sb.Append("client,");
   sb.Append("username,");
   sb.Append("user_id");
   sb.Append(") VALUES (");
   sb.Append(":client,");
   sb.Append(":username,");
   sb.Append("seq_user_id.nextval");
   sb.Append(") ");
   OracleCommand cmd = new OracleCommand(sb.ToString(), _conn);
   string[] ary_client = new string[Users.Count];
   string[] ary_username = new string[Users.Count];
   for (int i=0; i<Users.Count; i++)
   {
    User row=Users[i];
    ary_client[i]=row.client;
    ary_username[i]=row.username;
   }
   // prepare bind vars(bind in bulk using arrays)
   OracleParameter prm=new OracleParameter();
   cmd.Parameters.Clear();
   cmd.ArrayBindCount=Users.Count;
   cmd.BindByName=true;
   prm=new OracleParameter("client", OracleDbType.Varchar2); prm.Value=ary_client; cmd.Parameters.Add(prm);
   prm=new OracleParameter("username", OracleDbType.Varchar2); prm.Value=ary_username; cmd.Parameters.Add(prm);
   cmd.ExecuteNonQuery();
   trans.Commit();
   trans.Dispose();
  }
  catch {
   trans.Rollback();
   trans.Dispose();
   throw;
  }
 }
}

也许您应该将批量逻辑移植到plsql中
请参阅此处的示例:
http://dotnetslackers.com/articles/ado_net/BulkOperationsUsingOracleDataProviderForNETODPNET.aspx