我使用的一些旧代码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 可以加快速度(我还没有尝试过),但这需要对预先存在的存储过程进行太多更改。
答案 0 :(得分:0)
事实证明,ODP.NET没有提供一种通过数组绑定调整ExecuteNonQuery()
的“获取大小”的方法。因此,当存储过程包含OUT参数(或函数具有RETURN参数)时,Oracle会将每个项目的结果分别发送回调用方。这会导致大量网络开销,并显着减慢流程。
使用OracleDataAdapter.Update(DataSet)
时,执行结果将分批发送,从而降低网络开销。
如果没有OUT参数,使用ExecuteNonQuery()
而不是OracleDataAdapter.Update(DataSet)
要快得多。
答案 1 :(得分:0)
只是用我的经验来扩展答案。 将数组绑定用于插入、更新和删除的效果非常好,并且 ExecutNonQuery 正确返回受影响的行数。
但是由于 Merge ExecuteNonQuery 返回 -1 表示受影响的行数,您需要将 Rowcount 作为输出参数包含在内,这反过来又会再次减慢一切。