通过存储过程进行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();
试试这样的东西(未经测试,为简洁起见缩短):
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