PreparedStatement 、 CallableStatement 和性能注意事项

Posted

技术标签:

【中文标题】PreparedStatement 、 CallableStatement 和性能注意事项【英文标题】:PreparedStatement , CallableStatement and Performance Considerations 【发布时间】:2012-02-03 14:21:27 【问题描述】:

我有一个 oracle stored proc 需要从我的 Java 程序中调用。我曾使用CallableStatement 将参数传递给存储过程。我正在使用 oracle 瘦驱动程序(在 Web 逻辑服务器中针对相关的 jndi 条目进行配置)。这个存储的过程没有任何 OUT 值。这个存储过程接受一个数值,并根据接收到的值在数据库中进行大量更新。

我得到一个连接对象,然后在循环中调用这个存储过程(传递 20 个数字 20 次)。当我直接从 oracle 客户端调用此存储过程时,执行将在 2-3 秒内完成。但是,从我的 java 代码中无法预测该行为。有些电话甚至需要 30-40 秒才能完成。

我尝试使用 PreparedStatement 而不是 CallableStatement 并且可以看到边际性能提升(尽管行为仍然不一致)。

    鉴于 storedproc 没有任何 OUT 参数,就我而言是否可以使用 PreparedStatement 而不是 CallableStatementPreparedStatementCallableStatement 有一些性能提升,或者我可能没有正确观察到,有什么原因吗? 是否有更好的方法来解决此性能问题?

【问题讨论】:

你能贴出代码吗?或者,确认您的连接没有在每次迭代中建立(而不是重复使用一个连接),并确认您没有在每次迭代中调用conn.prepareCall()(而不是只有.setInt().execute() 在循环)。 您不止一次调用您的存储过程,对吗?您是否尝试过使用批量调用? docs.oracle.com/javase/1.3/docs/guide/jdbc/getstart/… 见 7.1.3 与其进行 20 次调用,不如尝试一个匿名的 PL/SQL 块(开始...调用 proc...调用 proc...end;)来调用您的存储过程 20次并使用匿名块对数据库进行一次调用。 我不允许在程序的 PL/SQL 部分上工作 :-( 正在进行单独的讨论以允许存储的 proc 将数字列表作为输入。对不起,如果我错误地理解了您的建议。 可以在 Java 端创建匿名 PL/SQL 块:CallableStatement cs = conn.prepareCall ("begin foo(?); end;"); 【参考方案1】:

你不应该考虑使用批处理吗?

conn.setAutoCommit(false);
CallableStatement stmt = conn.prepareCall(sql);
while(true) 
    stmt.setInt(1, value);
    stmt.addBatch();

stmt.executeBatch()
conn.commit();

【讨论】:

【参考方案2】:

根据您的评论,您的循环中有 prepareCall。准备好的语句(和可调用的语句)的一个优点是您可以准备一次,然后换出参数中传递的值;每次准备调用时都会产生开销,因此如果您可以将其带到循环之外,您可能会发现运行时间减少了。您可能会发现关闭 AutoCommit 也有帮助,因为每次提交都会产生开销。

conn.setAutoCommit(false);
CallableStatement stmt = conn.prepareCall(sql);
while(true) 
    stmt.setInt(1, value);
    stmt.execute();

conn.commit();
conn.setAutoCommit(true);

conn.setAutoCommit(true) 确实提交了,但我发现更明确)。

【讨论】:

谢谢马特。我明白了很多,我相信这会解决我的问题。我会试试这个和塞尔吉奥的建议。感谢您的时间和帮助:) 嗨,马特 - 尝试了您和 Sergio 建议的两种方法,但通过我的 java 代码执行时仍然很慢。 更新:我想程序本身现在很慢,当我尝试使用我的 oracle 客户端直接访问该程序时 - 每个数字大约需要 2 分钟。这在一天中的不同时间表现不同,这是我需要调查的事情。感谢您的所有帮助。 那为什么不做一个存储过程批量插入呢?

以上是关于PreparedStatement 、 CallableStatement 和性能注意事项的主要内容,如果未能解决你的问题,请参考以下文章

preparedstatement

Statement与PreparedStatement的区别

Java -- JDBC 学习--PreparedStatement

创建preparedstatement的多个实例

Preparedstatement对象

PreparedStatement对象