论坛首页 Java企业应用论坛

PreparedStatement一定会提高性能吗?

浏览 31677 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-06-10  
没有提高,第一次要20分,第二次将近17分钟:(
0 请登录后投票
   发表时间:2004-06-10  
agilejava
  单次运行PreparedStatement虽然要比Statement要慢一些,但是绝对不可能出现数量级的差异。

这是一篇蛮早的关于Oracle的JDBC性能测试文章,里面对比了thin和oci,PreparedStatment和Statment的差异,但是也没有像你这种情况差别巨大。
http://www.onjava.com/lpt/a/1480

是否你有什么设置的地方不正确?
0 请登录后投票
   发表时间:2004-06-11  
to Quake Wang:
我对Oracle不熟悉,是同事建好视图我查询就可以了,谁想有这么严重的问题:(
,你说的设置是指哪方面的,我问过同事,他们也没有给出我好的建议,用不用我把建视图的sql弄到这来了,可是用Statement查询时速度是挺快的啊,如果是视图的问题这方面有些怀疑。我先看看你给的那个文章,看看能不能发现解决办法。谢谢!:)
0 请登录后投票
   发表时间:2004-06-11  
来源:Java Programming with Oracle JDBC
http://www.oreilly.com/catalog/jorajdbc/chapter/ch19.html
里面有详细的图表说明为什么Statement比PreparedStatement快。

摘录一段如下:
There's a popular belief that using a PreparedStatement object is faster than using a Statement object. After all, a prepared statement has to verify its metadata against the database only once, while a statement has to do it every time. So how could it be any other way? Well, the truth of the matter is that it takes about 65 iterations of a prepared statement before its total time for execution catches up with a statement.

翻译过来就大概是说:
大家普遍误解PreparedStatment对象要比Statement对象效率高。毕竟,一个prepared statement只要校验一次,而一个普通statement每次都要校验。既然如此,在什么情况下后者会比前者效率高呢?事实是一个prepared statement要执行65次以上才能赶上一个普通statement的执行效率。

详细的内容大家自己看上面的连接吧。
0 请登录后投票
   发表时间:2004-06-11  
确实是好文,首先它纠正了PreparedStatement的效率一定会比Statement高这一看法,但是按照它的比较结果,和我这里的比较结果就差太多了。Statement查询就10秒,而PreparedStatement的查询时间刚才又测了一下,要30多分钟,搞死我了快
0 请登录后投票
   发表时间:2004-06-14  
其实PreparedStatement与statement性能差异是与数据库相关的
就应用来说,个人认为性能的差距微乎其微,一条糟糕的sql产生的损耗
远大于使用PreparedStatement或者statement带来的收益
除了性能之外,Statement可能会给你的oracle带来重编译过多的烦恼
严重点导致oracle崩溃,我们的项目中曾经出现过这样的情况。

至于一楼楼主的问题我怀疑是拿不同类型放在等式两边的原因
(类似where 数字类型=字符类型),请将全部java代码
建表语句,贴出。

例如:
select * from dcustmsg where phone_no='100001'
(这里的phone_no是numeric型)

#如下,摘自oracle的电子杂志:
执行许多SQL语句的JDBC程序产生大量的Statement和PreparedStatement对象。通常认为PreparedStatement对象比Statement对象更有效,特别是如果带有不同参数的同一SQL语句被多次执行的时候。PreparedStatement对象允许数据库预编译SQL语句,这样在随后的运行中可以节省时间并增加代码的可读性。

然而,在Oracle环境中,开发人员实际上有更大的灵活性。当使用Statement或PreparedStatement对象时,Oracle数据库会缓存SQL语句以便以后使用。在一些情况下,由于驱动器自身需要额外的处理和在Java应用程序和Oracle服务器间增加的网络活动,执行PreparedStatement对象实际上会花更长的时间。

然而,除了缓冲的问题之外,至少还有一个更好的原因使我们在企业应用程序中更喜欢使用PreparedStatement对象,那就是安全性。传递给PreparedStatement对象的参数可以被强制进行类型转换,使开发人员可以确保在插入或查询数据时与底层的数据库格式匹配。

当处理公共Web站点上的用户传来的数据的时候,安全性的问题就变得极为重要。传递给PreparedStatement的字符串参数会自动被驱动器忽略。最简单的情况下,这就意味着当你的程序试着将字符串“D'Angelo”插入到VARCHAR2中时,该语句将不会识别第一个“,”,从而导致悲惨的失败。几乎很少有必要创建你自己的字符串忽略代码。

在Web环境中,有恶意的用户会利用那些设计不完善的、不能正确处理字符串的应用程序。特别是在公共Web站点上,在没有首先通过PreparedStatement对象处理的情况下,所有的用户输入都不应该传递给SQL语句。此外,在用户有机会修改SQL语句的地方,如HTML的隐藏区域或一个查询字符串上,SQL语句都不应该被显示出来。
0 请登录后投票
   发表时间:2004-06-15  
下面是建立View的语句:
CREATE OR REPLACE VIEW CANCELUSER (
GATEWAY_ID, FEE_TERMINAL_ID, UNIFORMSERVICE_ID, REGISTER_DATE, CANCEL_DATE, CREATE_BY, CANCEL_BY );
 AS select century.anonymous_cancel_user.GATEID as GateWay_ID,  
     century.anonymous_cancel_user.USERPHONENUM as   Fee_Terminal_Id,
    13 as UniformService_id,
    to_char(century.anonymous_cancel_user.LASTCUSTDATE , 'yyyy-mm-dd hh24:mi:ss'); as Register_Date,
    to_char(century.anonymous_cancel_user.CREATEDATE, 'yyyy-mm-dd hh24:mi:ss'); as Cancel_Date,
    century.anonymous_cancel_user.CREATEBY as Create_By,
    century.anonymous_cancel_user.UPDATEBY as Cancel_By
from century.anonymous_cancel_user
where sysdate - createdate < 85

下面是我的测试程序:
String cancelSql = "select GateWay_ID,Fee_Terminal_Id,UniformService_id,Cancel_Date,Cancel_By from CancelUser where GateWay_ID=? and  Cancel_Date  >=? and Cancel_Date <? and Fee_Terminal_Id>=?";


Connection conn = null;
try {
      conn = DBUtil.getConnection(config);;
      PreparedStatement cancelStatement = conn.prepareStatement(cancelSql);;
      cancelStatement.setInt(1, 10);;
      cancelStatement.setString(2, "2004-06-06 10:10:10");;
      cancelStatement.setString(3, "2004-06-08 10:10:10");;                
      cancelStatement.setString(4, "1350000000");;

      UtilLog.debug("begin:", "test");;
      ResultSet cancelResult = cancelStatement.executeQuery();;
      while (cancelResult.next();); {
         System.out.println("fee_terminal_id:" + cancelResult.getString(1); + "test");;
      }
      UtilLog.debug("end:", "test");;  
} catch (Exception e); {
      e.printStackTrace();;
} finally {
       if (conn != null); {
             DBUtil.closeConnection(conn);;
      }
}

两个附件是用两种方法查询时的执行计划,希望对你的分析有帮助:)
再次感谢:)
0 请登录后投票
   发表时间:2004-06-15  
经过网友的帮助,终于解决了这个问题,原因在于fee_terminal_id建立了索引,而oracle在执行查询时按照这个索引先找到所有的行,之后再查询这些记录,而符合fee_terminal_id的记录有100多万,导致了查询速度非常之慢,在我把这个索引删除之后查询速度在8-9秒之间,很快。因此索引有时会起到相反的作用,要小心使用:)
非常感谢大家的帮助,特别要感谢卜志明,是他的帮助和指导帮助我找到了问题。:)
0 请登录后投票
   发表时间:2004-06-16  
很多情况下我是这样子的:

外层函数 call 内层函数
那个PreparedStatement是在内层里创建的,所以每调用一次内层函数都要重建一个PreparedStatement,这样内层的PreparedStatement创建起来只用了一次就被弃掉了,这样是不是不能起到Prepare的作用呢?还是只要是用Prepare过的,它会在服务器上缓存的。
  
0 请登录后投票
   发表时间:2004-06-16  
这得视数据库的不同而定
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics