`
zhang19841017
  • 浏览: 79758 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JDBC:预编译语句和批量更新-

阅读更多
JDBC:预编译语句和批量更新- -

                                     

进一步提高JDBC应用程序的性能 (四)

http://www.daima.com.cn/Info/55/Info15348/

bootcool@263.net

四:使用预编译语句和批量更新

首先我们得大致的了解数据库是怎么处理各种数据库操作语句的。当数据库接收到一个语句时,数据库引擎首先解析该语句,然后分析是否有语法,语义错误。如果没有错误,数据库将计算出如何高效的执行该语句。一旦得出执行策略,就由数据库引擎执行该语句,最后把执行结果反馈给用户。虽然数据库厂商对各自的数据库做了最大的优化,但是可以想象这的确是一个开销很大的工作。

于是,我们考虑如何使我们的数据库操作变得更高效呢?如果一条语句执行一次后,数据库就记录下该语句的执行策略,那么以后执行相同语句时,就可以省去上面的种种麻烦了。

Java里提供了这样的接口――PreparedStatement.。通过预编译PreparedStatement 对象, 我们能够很容易的提高语句执行效率。同时,需要指出的是Java里还有另一个实现数据库操作的接口――Statement,但是当语句格式固定时我们更倾向于使用PreparedStatement,只有当语句格式无法预见时,我们才考虑采用Statement。

以下是执行1000次语句结构相同的Insert,Update和Select语句的测试结果:



接口类型



Insert语句



Update语句



Select语句

第一次测试耗时



第二次测试耗时



第一次测试耗时



第二次测试耗时



第一次测试耗时



第二次测试耗时

Statement



2360 ms



2190 ms



3790 ms



3460 ms



3570 ms



2530 ms

PreparedStatement



1270 ms



1040 ms



2600 ms



2410 ms



440 ms



380 ms

                                     (表8)

分析: PreparedStatement 的效率明显比Statement要高出很多。另外,对于查询语句我们还得深入地看看JDBC是如何实现的。JDBC执行一次查询后,将返回一个 ResultSet(结果集)。为了建立这个结果集,JDBC将对数据库访问两次。第一次要求数据库对结果集中的各列进行说明,第二次告诉数据库,当程序需要获取数据时应如何安置这些数据。由此我们能够算出执行一次或多次查询,JDBC需要访问数据库的次数。

访问数据库次数 = 结果集中的列数 * 语句执行的次数 * 2



如果同样执行100次相同查询,结果集中的列数也相同时,假设为20列:

使用Statement:  访问数据库次数 = 20 * 100 * 2 = 4000  

使用Prepared Statement:  访问数据库次数 = 20 * 1* 2 = 400





以下是相关的测试结果:

方式



Select语句

执行100次语句结构相同的查询耗时



执行1000次语句结构相同的查询耗时

第一次测试



第二次测试



第一次测试



第二次测试

方式1



1100 ms



330 ms



3510 ms



3020 ms

方式2



110 ms



50 ms



440 ms



380 ms

                                   (表9)

分析:测试结果说明,如果不正确的使用了PreparedStatement接口,那么其执行效率和使用Statement没有什么差别,而PreparedStatement接口的优势也不会得到充分发挥。

最后我们还得补充一点,当我们需要成批插入或者更新记录时。我们考虑采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。如果我们再配合使用PreparedStatement接口,将进一步提高程序的性能。我们同样给出一个小程序予以说明。

import java.sql.*;

public class JDBCTEST3 {

  public static void main(String[] args) {
    try {String[] values = {"BeiJing","KunMing"};
          int[] results;

         Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
         Connection con = DriverManager.getConnection("jdbc:odbc:test");
           Statement st = con.createStatement ();
          for (int i = 0; i < values.length; i++){
             //把一个SQL命令加入命令列表
             st.addBatch ("INSERT INTO CITY VALUES('" + values[i] + "')");
          }
          //执行批量更新
          st.executeBatch ();

          PreparedStatement pst = con.prepareStatement("INSERT INTO CITY"
                                                       +"VALUES (?)");
  for (int i = 0; i < values.length; i++) {
            pst.setString(1, values[i]);
            //把一个SQL命令加入命令列表
pst.addBatch();
          }
          //执行批量更新
pst.executeBatch();
        
          st.close();
          pst.close();
          con.close();
   }
   catch(Exception ex){
    ex.printStackTrace();
   }
  }
}

  我们还要注意一点,如果使用PreparedStatement接口的方法不当,则不能达到提高执行效率的目的。我们用一个简单的测试程序说明:

import java.sql.*;
public class JDBCTEST2 {
private static Connection con = null;
private static String dbUrl = null;

public JDBCTEST2(){
}
public static void main(String args[]){
          try{
               dbUrl = "jdbc:odbc:test";
               Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
                 preparedStatementInsertTest_1();
                 System.out.println("===================");
                 preparedStatementInsertTest_2();
          }
          catch(Exception ex){
           ex.printStackTrace();
          }
  }

//方法1以不恰当的方式使用了PreparedStatement接口
public static void  preparedStatementInsertTest_1(){
      try{
            con = DriverManager.getConnection(dbUrl);
              PreparedStatement pst = null;
              long start = System.currentTimeMillis();
            
//执行1000次语句结构相同的查询
for(int i=0;i<1000;i++){
                 pst = con.prepareStatement("select * from s where s1 = " + i);
                 pst.executeQuery();
                 pst.close();
              }
              System.out.println("Methord_1 Execute Ellapse:"
                                +(System.currentTimeMillis()-start)
                                +"ms");
              con.close();
          }
        catch(Exception ex){
          ex.printStackTrace();
        }   
}

//方法2以正确的方式使用了PreparedStatement接口
public static void  preparedStatementInsertTest_2(){
      try{
            con = DriverManager.getConnection(dbUrl);
             long start = System.currentTimeMillis();
                PreparedStatement pst = null;
pst = con.prepareStatement("select * from s where s1 = ?");
              
//执行1000次语句结构相同的查询
for(int i=0;i<1000;i++){
                  pst.setInt(1,i);
                  pst.executeQuery();
              }
              System.out.println("Methord_2 Execute Ellapse:"
                                +(System.currentTimeMillis()-start)
                                +"ms");
              pst.close();
              con.close();
          }
        catch(Exception ex){
          ex.printStackTrace();
        }   
  }
}

分享到:
评论
1 楼 andyihk 2010-11-21  
lz的代码有点问题,我是照着lz的方法做的。但发现不行。应该加上
con.setAutoCommit(false)
Statement st = con.createStatement ();
          for (int i = 0; i < values.length; i++){
             //把一个SQL命令加入命令列表
             st.addBatch ("INSERT INTO CITY VALUES('" + values[i] + "')");
          }
          //执行批量更新
          st.executeBatch ();

          PreparedStatement pst = con.prepareStatement("INSERT INTO CITY"
                                                       +"VALUES (?)");
  for (int i = 0; i < values.length; i++) {
            pst.setString(1, values[i]);
            //把一个SQL命令加入命令列表
pst.addBatch();
          }
          //执行批量更新
pst.executeBatch();
con.commit();

相关推荐

    java_JDBC预编译相关知识点参照.pdf

    例如,批量插入、更新或删除数据时,如果SQL语句的基本结构不变,只是参数值不同,使用预编译语句可以在循环中多次设置参数并执行,显著提升性能。此外,由于预编译语句能有效防止SQL注入,所以涉及用户输入数据的...

    JDBC批量插入 更新 删除等操作

    它支持预编译SQL语句,提高了SQL语句的执行效率,同时还能有效防止SQL注入攻击。以下是具体的代码示例: ```java try { Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.get...

    语言程序设计资料:基于WEB的JAVA开发设计-JDBC.ppt

    - `PreparedStatement`增强了`Statement`,允许预编译SQL语句,提高性能并防止SQL注入。 - `CallableStatement`用于执行存储过程。 - `ResultSet`表示查询结果,提供了遍历数据的方法。 - `DatabaseMetaData`...

    mysql-connector-java-5.1.35 MySQL的jdbc驱动jar

    JDBC是Java语言中用来规范客户端程序如何访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC驱动则是实现JDBC规范的一系列Java类和接口,它充当了Java应用程序和数据库之间的桥梁。 `mysql-...

    PL/SQL Developer 中文帮助文档

    ### PL/SQL Developer 7.0 用户指南关键知识点解析 #### 一、介绍 - **PL/SQL Developer**是一款专为Oracle数据库设计的强大集成开发环境(IDE),它提供了丰富的...- **其它-更新与消息**:配置软件更新和消息通知。

    jdbc-批量插入数据

    在Java编程领域,JDBC(Java Database Connectivity)是连接Java应用程序和关系数据库的标准接口。...合理使用批量处理、预编译SQL语句以及数据库特有的优化功能,可以在处理大数据时获得显著的性能提升。

    JDBC的批量处理数据

    在JDBC中,批量处理主要分为两种类型:预编译语句的批量处理和非预编译语句的批量处理。预编译语句,也称为PreparedStatement,通常用于防止SQL注入攻击,同时由于其预先编译的特性,多次执行时性能更优。 1. **非...

    oracle-jdbc-12.2.0.1.zip

    7. **批处理**: 使用`Statement`的`addBatch()`和`executeBatch()`方法可以批量执行SQL插入、更新或删除操作,提高效率。 8. **游标**: Oracle JDBC支持游标,允许应用程序一次处理结果集中的一行数据,从而处理...

    JDBC操作技术 PDF

    - **PreparedStatement**:预编译的SQL语句,支持参数绑定,提高性能和安全性。 - **CallableStatement**:用于调用存储过程。 - **ResultSet**:执行查询后返回的数据集。 - **DriverManager**:管理数据库驱动,...

    ClickHouse-JDBCJar包.zip

    2. **创建Statement或PreparedStatement**:创建`Statement`对象用于执行静态SQL语句,或者创建`PreparedStatement`对象用于执行预编译的SQL语句,提高性能。 3. **执行SQL查询**:调用`Statement.executeQuery()`...

    4-尚硅谷JDBC每日单词.docx

    6. PreparedStatement:预编译语句对象,用于执行参数化的SQL语句。 7. ResultSet:结果集对象,用于存储查询结果。 JDBC核心类 1. java.sql.Connection:连接对象,用于建立与数据库的连接。 2. java.sql.Statement:...

    Java语言SQL接口—JDBC编程技术

    - Statement对象:用于执行SQL查询和更新语句,有三种形式:Statement、PreparedStatement和CallableStatement。 - ResultSet对象:存储查询结果,提供遍历查询结果的方法。 - PreparedStatement:预编译的SQL...

    《SQL预编译和批量提交对性能提升效果探索》测试代码

    例如,在Java的JDBC中,我们可以使用PreparedStatement对象来实现预编译,它的优点在于减少解析和编译SQL语句的时间,提升执行速度。 接着,我们来讨论批量提交。在传统的数据库操作中,每次插入、更新或删除操作...

    jdbc基础------jdbc

    Java Database Connectivity(JDBC)是Java平台中用于与关系型数据库交互的标准API,它允许Java程序通过编写Java代码来执行SQL语句,进行数据查询、插入、更新和删除等操作。了解并熟练掌握JDBC的基础知识,对于Java...

    jdbc批量插入大字段

    2. **创建PreparedStatement**:预编译SQL插入语句,例如`INSERT INTO table_name (blob_column) VALUES (?)`。使用PreparedStatement可以避免SQL注入,并为批处理做好准备。 3. **设置Blob参数**:为每个Blob值...

    oracle.jdbc.driver.oracledriver Oracle JDBC驱动包 ojdbc6

    - **性能优化**:使用`PreparedStatement`代替`Statement`,预编译SQL语句,提高执行效率。同时,合理设置连接池大小和超时时间,避免资源浪费。 - **错误处理**:正确捕获和处理异常,确保应用程序的健壮性。 总之...

    jdbc jar包

    在Java应用程序中,JDBC扮演着桥梁的角色,允许程序执行SQL语句,进行数据查询、插入、更新和删除等操作。 **1. JDBC API概述** JDBC API主要由以下组件构成: - `java.sql.DriverManager`: 它是JDBC的核心,负责...

    jdbc驱动jar 包

    在IT行业中,数据库连接是应用程序与数据库交互的关键环节,而JDBC(Java Database Connectivity)是Java编程语言中用于规范客户端程序如何访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。...

    JDBC与Oracle

    3. 使用批处理:批量提交SQL语句可以减少网络往返次数,提高性能。 4. 超时设置:合理设置连接和查询超时,避免程序因长时间等待而阻塞。 **异常处理** 在JDBC编程中,应捕获并处理常见的数据库异常,如`...

Global site tag (gtag.js) - Google Analytics