.net - 在数组绑定(bind)中使用直接路径加载提示是否错误?

标签 .net database oracle oracle11g odp.net

作为迁移任务的一部分,我试图通过 .NET 应用程序(使用 ODP.NET)使用数组绑定(bind)将大量数据 (>30M) 插入到一个 1000/10000 行 block 的表中;有用。我认为如果我直接使用路径加载提示 /*+ APPEND_VALUES */ 会更快。但每当我尝试这样做时,我都会遇到异常:ORA-38910:BATCH ERROR MODE is not supported for this operation。在跟踪文件中(由 tkprof 收集,没有 sys)我发现了这些:

...

********************************************************************************

insert /*+ APPEND_VALUES */ into MYTABLE(COL1, COL2)
values (:COL1, :COL2)

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      2      0.00       0.00          0          0          0           0
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.00       0.00          0          0          0           0

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 122  

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  LOAD AS SELECT  (cr=0 pr=0 pw=0 time=0 us)
      0   BULK BINDS GET  (cr=0 pr=0 pw=0 time=0 us)


Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       2        0.00          0.00
  SQL*Net message from client                     2        3.14          3.20
  SQL*Net break/reset to client                   2        0.00          0.00
********************************************************************************

declare
  m_stmt  varchar2(512);
begin
   m_stmt:='delete from sdo_geor_ddl__table$$';
   EXECUTE IMMEDIATE m_stmt;
   EXCEPTION
     WHEN OTHERS THEN
       NULL;
end;

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           1
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.00       0.00          0          0          0           1

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 57     (recursive depth: 1)
********************************************************************************

SQL ID: 3972rvxu3knn3
Plan Hash: 3007952250
delete from sdo_geor_ddl__table$$


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.00       0.00          0          0          0           0

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 57     (recursive depth: 2)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  DELETE  SDO_GEOR_DDL__TABLE$$ (cr=0 pr=0 pw=0 time=0 us)
      0   TABLE ACCESS FULL SDO_GEOR_DDL__TABLE$$ (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)


... summary from here

我使用的代码:

private void TestArrayBindWithHint()
{
    var data = new List<MyTableData>();

    // ...
    // data fetching + populating code here....
    // ...

    // Insert
    using(var connection = GetConnection())
    {
        var insertQuery = "insert /*+ APPEND_VALUES */ into MYTABLE(COL1, COL2) values (:COL1, :COL2)";
        using (var command = connection.CreateCommand())
        {
            command.CommandText = insertQuery;
            command.CommandType = CommandType.Text;
            command.BindByName = true;
            command.ArrayBindCount = data.Count;

            command.Parameters.Add(":COL1", OracleDbType.Int64, data.Select(d => d.COL1).ToArray(), ParameterDirection.Input);
            command.Parameters.Add(":COL2", OracleDbType.Byte, data.Select(d => d.COL2).ToArray(), ParameterDirection.Input);
            command.ExecuteNonQuery();
        }
    }
}

private ManagedDataAccess.Client.OracleConnection GetConnection()
{
    const string identifier = "MYAPP";
    var connection = new ManagedDataAccess.Client.OracleConnection(ConfigurationManager.AppSettings["connectionString"]);   
    connection.Open();
    connection.ClientId = identifier;
    ExecuteNonQuery(connection, string.Format(@"ALTER SESSION SET TRACEFILE_IDENTIFIER = ""{0}""", identifier));

    return connection;
}

所以我的问题是:

  • 在数组绑定(bind)中使用直接路径加载提示是否错误?如果不是,我如何通过 ODP.NET 使用它?
  • 跟踪中的 delete from sdo_geor_ddl__table$$ DDL 是什么?为什么要生成它?

最佳答案

/*+ APPEND_VALUES */ 提示 Oracle 11.2 中引入的全新提示

通常,当您进行批量操作时,您会使用 FORALL ... SAVE EXCEPTIONS 语句,请参阅 FORALL .使用可选的 SAVE EXCEPTIONS 可以访问 SQL%BULK_EXCEPTIONS 属性,您可以在其中检索单个记录的异常。

当您使用 /*+ APPEND_VALUES */ 提示时,SQL%BULK_EXCEPTIONS 属性不可用,即您不能使用 SAVE EXCEPTIONS。就我个人而言,我认为这是 Oracle 中的一个错误,也许会在未来的版本中得到纠正。

显然 ODP.NET ExecuteNonQuery() 方法在内部始终以“批处理错误模式”运行,参见 Execution Modes of OCIStmtExecute() .这会导致错误。我看不到关闭“批处理错误模式”的任何可能性,因此您必须在没有 /*+ APPEND_VALUES */ 提示的情况下运行您的插入。

关于.net - 在数组绑定(bind)中使用直接路径加载提示是否错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40779201/

相关文章:

oracle - 如何在 PL/SQL 中对数字表进行排序?

Python Sqlite3 : Create a schema without having to use a second database

node.js - MongoDB + NodeJS Web 应用程序的初始数据库结构/数据

sql - Oracle ORA-04030 即使在循环中使用绑定(bind)变量

c# - WIF 和子域

database - Cassandra Geolocation,索引还是不索引?

java - 如何在 Oracle AQ 中停止在未经确认的情况下删除消息?

c# - 我无法使用 C# 进行语音识别。为什么?

.net - 如何保护我的 .NET 应用程序免受 DLL 劫持?

.net - RegFree COM 从 C# 工作,而不是从 VBA 工作