1

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

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

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


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

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

    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会加快速度(我还没有尝试过),但这需要对预先存在的存储过程进行太多更改。

4

2 回答 2

1

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

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

当没有 OUT 参数时,使用起来ExecuteNonQuery()OracleDataAdapter.Update(DataSet).

于 2014-06-17T21:54:08.353 回答
0

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

但是因为 Merge ExecuteNonQuery 为受影响的行数返回 -1,所以您需要将 Rowcount 作为输出参数包括在内,这反过来又会降低一切速度。

于 2021-06-18T05:57:35.207 回答