使用Oracle客户端在Oracle数据库中高效地插入多个记录

j2cgzkjk  于 2023-01-01  发布在  Oracle
关注(0)|答案(4)|浏览(158)

我有一个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; 
}

}

bmvo0sr5

bmvo0sr51#

将数据加载到表中最快的方法是datapump(impdp实用程序),另一种快速方法是SQL*Loader。
如果你想坚持使用C#,那就看看批量操作。

x3naxklr

x3naxklr2#

我经常使用SQL*Loader从C#将记录批量加载到stage。
代码的主要内容如下所示:

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;
}

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

ergxz8rk

ergxz8rk3#

我正在向位于澳大利亚的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

卡洛斯·梅里吉。

w51jfk4q

w51jfk4q4#

您可能不得不放弃"DataAdapter"代码以获得任何真正的性能。
下面是看起来像是目标的dotnet类。

    • Oracle.数据访问.客户端. 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/

相关问题