`
fengpeng
  • 浏览: 102450 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

PreparedStatement真的比Statement快吗?

阅读更多
关键字: 企业应用   jdbc    

从开始写java程序就一直被灌输着一种思想,如果使用jdbc一定要使用PreparedStatement,而不要使用Statement对象。
其中的原因有好多,比如可以防止SQL注入攻击,防止数据库缓冲池溢出,代码的可读性,可维护性。这些都很正确。
但是还有一点人们经常提的就是PreparedStatement能够显著的提高执行效率。
看了两篇关于PreparedStatement和Statement的帖子
http://dev2dev.bea.com.cn/bbs/thread.jspa?forumID=121&threadID=10397&start=0&tstart=0
http://www.iteye.com/topic/5631?page=1
里面提到,PreparedStatement并不一定比Statement快,于是想自己动手测试一下
一共分5种情况测试

代码
  1. stmt      pre-stmt     
  2. --1:每次都单独连数据库--100条   
  3. 21.936  22.076  
  4. 22.05     22.051       
  5. 22.172  22.178     
  6. --2:Stmt使用相同的SQL语句,参数值也相同--100条   
  7. 0.78      0.796    
  8. 0.718     0.749    
  9. 0.749     0.764    
  10. --3:Stmt使用相同的SQL语句,参数值不同--100条   
  11. 0.967     0.749    
  12. 0.78      0.874    
  13. 0.749     0.749    
  14. --4:Stmt使用相同的SQL语句,参数值也相同--10000条   
  15. 33.079  36.154     
  16. 34.156  39.306     
  17. 34.359  36.138     
  18. --5:Stmt使用相同的SQL语句,参数值不同--10000条   
  19. 32.799  34.125     
  20. 32.564  35.53      
  21. 35.701  34.952     
  22. 32.582  40.798     
  23. 38.893  42.345     
  24. 35.082  41.736     
<script>render_code();</script>
分析:
第一种情况:
由于我测试时采用jdbc直接链接数据库,所以在第一种情况下插入速度很慢,时间都消耗在了数据库链接的创建上了,符合常理,没什么疑义。
第二种情况:
由于使用Statement插入时sql语句都相同,我通过阅读上面的两篇帖子,猜想可能是Statement语句也被DB缓存了,所以跟
PreparedStatement速度差不多,我想如果每次插入的sql都不同,那么Statement应该慢下来了吧。
第三种情况:
并非像我在执行第二种情况时想象的那样,PreparedStatement还是跟Statement差不多,于是我想是不是数据量不够大呀,于是我增大了
插入数据量,希望PreparedStatement能够比Statement快些
第四/五种情况:
测试结果PreparedStatement反到更慢了。

PreparedStatement什么情况下才会比Statement快?那位大侠来指点一下!

代码如下:
DDL
代码
  1. CREATE TABLE dbo.jdbc_stmt    
  2. (   
  3.     id   numeric(10,0) IDENTITY,   
  4.     name varchar(10)   NOT NULL,   
  5.     grad int           NOT NULL,   
  6.     age  int           NOT NULL,   
  7.     dept int           NOT NULL   
  8. )   
<script>render_code();</script>
测试程序
代码
  1. public void jdbcStmtPerformance()   
  2.     {   
  3.         //1:每次都单独连数据库--100条   
  4. //      String stmtSQL = "insert into jdbc_stmt values('ivanl',2,25,1001)";   
  5. //      for(int i = 0; i< 100; i++)   
  6. //      {   
  7. //          logger.debug("stmt #"+i);   
  8. //          getJdbcTemplate().update(stmtSQL);   
  9. //      }   
  10.            
  11.         //2:Stmt使用相同的SQL语句,参数值也相同--100条   
  12. //      getJdbcTemplate().execute(new StatementCallback(){   
  13. //          public Object doInStatement(Statement stmt) throws SQLException   
  14. //          {   
  15. //              String stmtSQL = "insert into jdbc_stmt values('ivanl',2,25,1001)";   
  16. //              for(int i = 0; i< 100; i++)   
  17. //              {   
  18. //                  logger.debug("stmt #"+i);   
  19. //                  stmt.executeUpdate(stmtSQL);   
  20. //              }   
  21. //              return null;   
  22. //          }   
  23. //      });   
  24.            
  25.         //3:Stmt使用相同的SQL语句,参数值不同--100条   
  26. //      getJdbcTemplate().execute(new StatementCallback(){   
  27. //          public Object doInStatement(Statement stmt) throws SQLException   
  28. //          {   
  29. //              String stmtSQL = "insert into jdbc_stmt values('ivanl',2,25,";   
  30. //              for(int i = 0; i< 100; i++)   
  31. //              {   
  32. //                  logger.debug("stmt #"+i);   
  33. //                  stmt.executeUpdate(stmtSQL+i+")");   
  34. //              }   
  35. //              return null;   
  36. //          }   
  37. //      });   
  38.            
  39. //      4:Stmt使用相同的SQL语句,参数值也相同--10000条   
  40. //      getJdbcTemplate().execute(new StatementCallback(){   
  41. //          public Object doInStatement(Statement stmt) throws SQLException   
  42. //          {   
  43. //              String stmtSQL = "insert into jdbc_stmt values('ivanl',2,25,1001)";   
  44. //              for(int i = 0; i< 10000; i++)   
  45. //              {   
  46. //                  logger.debug("stmt #"+i);   
  47. //                  stmt.executeUpdate(stmtSQL);   
  48. //              }   
  49. //              return null;   
  50. //          }   
  51. //      });   
  52.            
  53. //      5:Stmt使用相同的SQL语句,参数值不同--10000条   
  54.         getJdbcTemplate().execute(new StatementCallback(){   
  55.             public Object doInStatement(Statement stmt) throws SQLException   
  56.             {   
  57.                 String stmtSQL = "insert into jdbc_stmt values('ivanl',2,25,";   
  58.                 for(int i = 0; i< 10000; i++)   
  59.                 {   
  60.                     logger.debug("stmt #"+i);   
  61.                     stmt.executeUpdate(stmtSQL+i+")");   
  62.                 }   
  63.                 return null;   
  64.             }   
  65.         });   
  66.     }   
  67.        
  68.        
  69.     public void jdbcPreStmtPerformance()   
  70.     {   
  71.         //1:每次都单独连数据库--100条   
  72. //      String stmtSQL = "insert into jdbc_stmt values(?,?,?,?)";   
  73. //      for(int i = 0; i< 100; i++)   
  74. //      {   
  75. //          logger.debug("pre-stmt #"+i);   
  76. //          getJdbcTemplate().update(stmtSQL, new Object[]{"ivanl", new Integer(2), new Integer(25), new Integer(1002)});   
  77. //      }   
  78.            
  79.         //2:Stmt使用相同的SQL语句,参数值也相同--100条   
  80. //      String stmtSQL = "insert into jdbc_stmt values(?,?,?,?)";   
  81. //      getJdbcTemplate().execute(stmtSQL,new PreparedStatementCallback(){   
  82. //          public Object doInPreparedStatement(PreparedStatement ps)  throws SQLException   
  83. //          {   
  84. //              for(int i = 0; i< 100; i++)   
  85. //              {   
  86. //                  logger.debug("pre-stmt #"+i);   
  87. //                  ps.setString(1, "ivanl");   
  88. //                  ps.setInt(2, 2);   
  89. //                  ps.setInt(3, 25);   
  90. //                  ps.setInt(4, 1002);   
  91. //                  ps.execute();   
  92. //              }   
  93. //              return null;   
  94. //          }   
  95. //      });   
  96.         //3:Stmt使用相同的SQL语句,参数值不同--100条   
  97. //      String stmtSQL = "insert into jdbc_stmt values(?,?,?,?)";   
  98. //      getJdbcTemplate().execute(stmtSQL,new PreparedStatementCallback(){   
  99. //          public Object doInPreparedStatement(PreparedStatement ps)  throws SQLException   
  100. //          {   
  101. //              for(int i = 0; i< 100; i++)   
  102. //              {   
  103. //                  logger.debug("pre-stmt #"+i);   
  104. //                  ps.setString(1, "ivanl");   
  105. //                  ps.setInt(2, 2);   
  106. //                  ps.setInt(3, 25);   
  107. //                  ps.setInt(4, i);   
  108. //                  ps.execute();   
  109. //              }   
  110. //              return null;   
  111. //          }   
  112. //      });   
  113.         //4:Stmt使用相同的SQL语句,参数值也相同--10000条   
  114. //      String stmtSQL = "insert into jdbc_stmt values(?,?,?,?)";   
  115. //      getJdbcTemplate().execute(stmtSQL,new PreparedStatementCallback(){   
  116. //      public Object doInPreparedStatement(PreparedStatement ps)  throws SQLException   
  117. //      {   
  118. //          for(int i = 0; i< 10000; i++)   
  119. //          {   
  120. //              logger.debug("pre-stmt #"+i);   
  121. //              ps.setString(1, "ivanl");   
  122. //              ps.setInt(2, 2);   
  123. //              ps.setInt(3, 25);   
  124. //              ps.setInt(4, 1002);   
  125. //              ps.execute();   
  126. //          }   
  127. //          return null;   
  128. //      }   
  129. //  });   
  130.         //5:Stmt使用相同的SQL语句,参数值不同--10000条   
  131.         String stmtSQL = "insert into jdbc_stmt values(?,?,?,?)";   
  132.         getJdbcTemplate().execute(stmtSQL,new PreparedStatementCallback(){   
  133.             public Object doInPreparedStatement(PreparedStatement ps)  throws SQLException   
  134.             {   
  135.                 for(int i = 0; i< 10000; i++)   
  136.                 {   
  137.                     logger.debug("pre-stmt #"+i);   
  138.                     ps.setString(1"ivanl");   
  139.                     ps.setInt(22);   
  140.                     ps.setInt(325);   
  141.                     ps.setInt(4, i);   
  142.                     ps.execute();   
  143.                 }   
  144.                 return null;   
  145.             }   
  146.         });   
  147.            
  148.     }   
分享到:
评论

相关推荐

    java中PreparedStatement和Statement的区别

    Java 中 PreparedStatement 和 Statement 的区别 Java 中的 PreparedStatement 和 Statement 都是用于执行 SQL 语句的接口,但是它们之间存在一些关键的区别。 首先,从数据库执行 SQL 语句的角度来看,使用 ...

    Statement和PreparedStatement之间的区别

    这种差异导致PreparedStatement对象执行速度更快,特别是在执行多次相同的SQL语句时。 其次,PreparedStatement对象可以避免SQL注入攻击。在 Statement 对象中,如果用户输入的数据包含恶意代码,例如 Drop 表名,...

    34.jdbc中preparedStatement比Statement的好处.avi

    jdbc中preparedStatement比Statement的好处

    PreparedStatement和Statement

    - **性能**:由于预编译,`PreparedStatement`通常比`Statement`更快,尤其是在大量重复执行相同SQL时。 - **安全性**:`PreparedStatement`通过占位符防止SQL注入,而`Statement`则容易受到这类攻击。 - **...

    Java面试题34.jdbc中preparedStatement比Statement的好处.mp4

    Java面试题34.jdbc中preparedStatement比Statement的好处.mp4

    如何获得PreparedStatement最终执行的sql语句

    一种可能的方法是通过日志配置,例如,启用MySQL的`Statement`和`PreparedStatement`日志,这样在执行时会打印出详细的SQL语句。 另外,开发工具如IntelliJ IDEA、Eclipse等,或者数据库管理工具如MySQL Workbench...

    关于PreparedStatement插入Date类型值的方法.txt

    `PreparedStatement`是`Statement`接口的子接口,用于预编译SQL语句,并可以重复执行这些预编译过的SQL语句。这不仅能够提高应用程序的性能,还能提高安全性,因为它支持参数化查询,避免了SQL注入的风险。 #### 二...

    PreparedStatement详细用法

    ### PreparedStatement的详细...综上所述,无论从性能、安全性还是数据库无关性的角度,`PreparedStatement`都是比`Statement`更为优秀的选择,因此,在实际开发中,应尽可能地采用`PreparedStatement`来执行SQL语句。

    connection 和 preparedstatement 的关闭问题

    #### 何时使用 Statement? - 当SQL语句简单,不会重复执行时。 - 对于读取数据的操作,如果数据量不大,可以考虑使用`Statement`。 - 当不需要参数化SQL语句时,例如只读操作。 #### 何时使用 PreparedStatement...

    prepareStatement和Statement的区别

    首先,从创建时的区别开始,Statement 需要通过 Connection 对象的 createStatement() 方法创建,而 PreparedStatement 需要通过 Connection 对象的 prepareStatement() 方法创建,并且需要带有 SQL 语句。...

    JDBC基础教程之PreparedStatement.doc

    `PreparedStatement`的主要特点在于它可以预先编译SQL语句,并允许用户在执行前动态地设置SQL语句中的参数值,这使得它在执行相同或相似SQL语句时比普通的`Statement`更加高效。 #### 二、`PreparedStatement`与`...

    PreparedStatement接口

    NULL 博文链接:https://chaoyi.iteye.com/blog/2088080

    PreparedStatement 详细用法

    在Java编程语言中,`PreparedStatement`是`java.sql`包中的一个接口,它继承自`Statement`类,并提供了预编译SQL语句的功能。预编译SQL语句的主要优势在于提高了执行效率和安全性。尤其在处理动态查询或频繁执行相同...

    statement和prepared区别

    PreparedStatement对象的创建和预编译过程比Statement更为复杂和耗时。因此,在那些对性能要求极高且SQL语句几乎不重复执行的应用场景下,或许需要根据具体情况来权衡利弊。 总之,理解Statement和...

    练习3:使用PreparedStatement插入宠物信息.zip

    在Java编程中,PreparedStatement是Java SQL API中的一个接口,它是Statement接口的子接口。这个练习主要涉及如何使用PreparedStatement来插入宠物信息到数据库中。PreparedStatement的主要优势在于它的预编译能力和...

    详解Java的JDBC中Statement与PreparedStatement对象

    在Java的JDBC(Java Database Connectivity)中,与数据库交互的核心接口是Statement和PreparedStatement。这两个接口都是用于执行SQL语句的,但它们在特性和效率上有所不同。 Statement接口是最基本的SQL执行方式...

    JDBC(用PrepareStatement实现)

    在实际开发中,为了提高效率和安全性,我们通常会使用PreparedStatement接口来代替Statement接口。 1. **PreparedStatement简介** PreparedStatement是Statement的一个子接口,它的主要优势在于预编译。预编译的...

    PreparedStatement 向数据库插入时间方法

    ### PreparedStatement 向数据库插入时间方法 #### 背景与问题描述 在Java应用程序中,我们经常需要将数据写入数据库。为了确保SQL查询的安全性和效率,通常会使用`PreparedStatement`来执行这样的操作。然而,在...

    06丨数据库原理:为什么PrepareStatement性能更好更安全?.pdf

    在数据库编程中,我们经常遇到两种执行SQL语句的方法:Statement和PreparedStatement。尽管Statement看起来更简洁,但在实际应用中,尤其是在使用ORM框架如MyBatis时,PreparedStatement成为了首选。那么,为什么...

Global site tag (gtag.js) - Google Analytics