【问题标题】:Efficiently inserting multiple records in oracle db using Oracle client使用 Oracle 客户端在 oracle db 中高效插入多条记录
【发布时间】:2011-10-03 17:05:03
【问题描述】:

我有 C#-WCF/Winforms 应用程序。它使用 Oracle 客户端 API 和具有简单插入查询的存储过程在 Oracle 数据库的临时表中插入 450,000 多条记录。 在数据库中插入记录大约需要 15 分钟,有时记录也不会被插入。在 wcf 端出现各种超时错误。 有没有什么有效的方法来做这些插入?

感谢阅读。

这是我的批量插入代码:

OracleTransaction tran = null; 
UpdateRowSource oldURS = this.cmd.UpdatedRowSource; 
OracleCommand oldCmd = this.dbAdapter.InsertCommand; 
int oldUBS = this.dbAdapter.UpdateBatchSize; 
try 
{ 
    SetOutputParams(); 
    this.OpenDBConnection(); 
    tran = this.dbConn.BeginTransaction(); 
    this.cmd.Transaction = tran; 
    this.cmd.UpdatedRowSource = UpdateRowSource.OutputParameters; 
    this.dbAdapter.InsertCommand = this.cmd; 
    this.dbAdapter.UpdateBatchSize = size; 
    this.dbAdapter.Update(data); 
    tran.Commit(); 
    SetOutputParamValues(); 
} 
catch (OracleException ex) 
{ 
    if (tran != null) { 
        tran.Rollback(); 
    } 
    throw; 
} 
finally 
{ 
    this.CloseDBConnection(); 
    this.cmd.Parameters.Clear(); 
    this.cmd.UpdatedRowSource = oldURS; 
    this.dbAdapter.InsertCommand = oldCmd; 
    this.dbAdapter.UpdateBatchSize = oldUBS; 
} 

}

【问题讨论】:

  • 在 C# 中,使用 throw 而不是 throw ex 否则你的 StackTrace 会被搞砸:stackoverflow.com/questions/178456/…
  • 是的,同意 Davide。我将使用 throw;代替。谢谢。
  • 这是基于 Sql Server 的。(url) 但可能会给您一些关键字来搜索“基于集合”。 docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/…我不确定oracle有这个概念。使用 sql server,我还将 xml 发送到存储过程,在那里解析(“粉碎”)xml,并进行批量插入。但 IIRC,dataadapter 的默认行为是 RBAR(逐行列)

标签: c# sql oracle plsql


【解决方案1】:

将数据加载到表中的最快方法是 datapump(impdp 实用程序)。 另一种快速方法是 SQL*Loader。

如果您想坚持使用 C#,请查看批量操作。 我的 google 业力找到了the following examples

【讨论】:

    【解决方案2】:

    我经常从 C# 使用 SQL*Loader 将记录批量加载到阶段。

    代码的内容是这样的:

    public string RunSqlLdr(string user, string password, string dsn, string fileNameCtl, string fileNameLog)
    {
        // Redirect both streams so we can write/read them.
        var cmdProcessInfo = new System.Diagnostics.ProcessStartInfo("cmd.exe")
        {
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            UseShellExecute = false
        };
    
        // Start the process. 
        var process = System.Diagnostics.Process.Start(cmdProcessInfo);
    
        // Issue the sqlldr command and exit.
        process.StandardInput.WriteLine("cd " + _directoryPath);
        process.StandardInput.WriteLine("sqlldr " + user + "/" + password + "@" + dsn + " control=" + fileNameCtl + " log=" + fileNameLog);
        process.StandardInput.WriteLine("exit");
    
        // Read all the output generated from it.
        var output = process.StandardOutput.ReadToEnd();
        process.Dispose();
    
        return output;
    }
    

    这将返回命令行的输出,但您还需要检查生成的日志文件中的加载记录和错误计数等。

    【讨论】:

      【解决方案3】:

      我将大量数据插入到位于澳大利亚的 Oracle 数据库中,远离我在 C# 中运行客户端应用程序的地方。

      这是我如何做的总结。使用数组绑定插入数十万条记录的速度之快让我感到惊讶。

      这不是确切的代码,但你明白了:

      using System.Data.OleDb;
      
      int numRecords = 2;
      int[] DISTRIBNO = new int[numRecords];
      DISTRIBNO[0] = 100;
      DISTRIBNO[1] = 101;
      
      string sql = "INSERT INTO Distributors (distribno) VALUES (:DISTRIBNO)";
      cnn = new Oracle.DataAccess.Client.OracleConnection(conString);
      cnn.Open();
      
      using (Oracle.DataAccess.Client.OracleCommand cmd = cnn.CreateCommand())
      {
          cmd.CommandText = sql;
          cmd.CommandType = CommandType.Text;
          cmd.BindByName = true;
          // To use ArrayBinding, we need to set ArrayBindCount                
          cmd.ArrayBindCount = numRecords;
          cmd.CommandTimeout = 0;
      
          cmd.Parameters.Add(
                    ":DISTRIBNO", 
                    Oracle.DataAccess.Client.OracleDbType.Int32, 
                    BR_VOLMONTH,
                    ParameterDirection.Input);
      
          cmd.ExecuteNonQuery();
      }//using
      

      卡洛斯·梅里赫。

      【讨论】:

        【解决方案4】:

        您可能必须放弃“DataAdapter”代码才能获得真正的性能。

        这是似乎是目标的 dotnet 类。

        Oracle.DataAccess.Client.OracleBulkCopy

        OracleBulkCopy 类

        OracleBulkCopy 对象有效地将数据从另一个数据源批量加载或复制到 Oracle 表中。

        https://docs.oracle.com/cd/E11882_01/win.112/e23174/OracleBulkCopyClass.htm#ODPNT7446

        https://docs.oracle.com/cd/E85694_01/ODPNT/BulkCopyCtor3.htm

        …………

        这是来自(oracle 拥有的)ODP.NET。

        https://www.nuget.org/packages/Oracle.ManagedDataAccess/

        【讨论】:

        • 并使用一些疯狂的互联网搜索技巧,我发现了这个:c-sharpcorner.com/article/… 它使用(正如我的回答指出的那样):“使用 Oracle.ManagedDataAccess.Client;”
        猜你喜欢
        • 2018-01-16
        • 1970-01-01
        • 2021-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多