ODP.NET数组绑定return / OUT param性能

时间:2013-12-09 21:52:20

标签: c# performance oracle odp.net executenonquery

我使用的一些旧代码OracleDataAdaper.Update(DataSet)。如果我调用测试存储过程(只有输入参数),则插入20,000行需要大约24秒。我需要改进,所以我切换到使用数组绑定。使用数组绑定ExecuteNonQuery()需要不到3秒的时间来插入相同的20,000行!这是一个巨大的性能提升,我也避免创建昂贵的DataSet。

但是,我遇到了包含OUT参数的存储过程或返回值的函数的问题。

使用OracleDataAdaper.Update(DataSet)通过具有OUT参数的存储过程插入相同的20,000行大约需要26秒 - 比没有OUT参数慢2秒或8% - 不错。
但是使用数组绑定调用相同的存储过程导致ExecuteNonQuery()运行15分钟!这比没有OUT参数慢300%!


对于可变长度类型的所有OUT / IN OUT / RETURN参数(即VARCHAR2),我将OracleParameter.ArrayBindSize属性设置为int[numOfRows],并将所有值设置为类型的最大值(即,对于VARCHAR2为4000) )。

我的测试存储过程看起来像这样(在现实生活中,我可能会返回一个序列号):

    PROCEDURE INSERT_TEST(
        p_key            VARCHAR2,
        p_id             NUMBER,
        p_dt             DATE,
        p_unique_key OUT VARCHAR2)
      AS
      BEGIN
        INSERT INTO T_TEST_DAL(
                      UNIQUE_KEY,
                      NUM_ID,
                      DT_VAL)
        VALUES (
                 p_key,
                 p_id,
                 p_dt)
        RETURNING UNIQUE_KEY
          INTO p_unique_key;
    END INSERT_TEST;

我使用ODP.NET Oracle.DataAccess v4.112.3.0,但我非常确定它不是特定于版本的。

是否有人遇到过与数组绑定的OUT参数类似的问题?我是否需要为OUT / return参数设置另一个属性以加快速度?

我希望实现的目标是提高性能,而无需在数据库方面进行更改。也许使用 PLSQLAssociativeArray 可以加快速度(我还没有尝试过),但这需要对预先存在的存储过程进行太多更改。

2 个答案:

答案 0 :(得分:0)

事实证明,ODP.NET没有提供一种通过数组绑定调整ExecuteNonQuery()的“获取大小”的方法。因此,当存储过程包含OUT参数(或函数具有RETURN参数)时,Oracle会将每个项目的结果分别发送回调用方。这会导致大量网络开销,并显着减慢流程。

使用OracleDataAdapter.Update(DataSet)时,执行结果将分批发送,从而降低网络开销。

如果没有OUT参数,使用ExecuteNonQuery()而不是OracleDataAdapter.Update(DataSet)要快得多。

答案 1 :(得分:0)

只是用我的经验来扩展答案。 将数组绑定用于插入、更新和删除的效果非常好,并且 ExecutNonQuery 正确返回受影响的行数。

但是由于 Merge ExecuteNonQuery 返回 -1 表示受影响的行数,您需要将 Rowcount 作为输出参数包含在内,这反过来又会再次减慢一切。