zoukankan      html  css  js  c++  java
  • Java 之 JDBC:(五)批量插入

    一、批量执行 SQL 语句

      1、当需要成批插入或者更新记录时,可以采用 Java 的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。

      2、使用 PreparedStatement 可以实现批量数据的操作。

      3、update、delete 本身就具有批量操作的效果。此时的批量操作,主要指的是批量插入,使用 PreparedStatement 实现高效的批量插入操作。

      4、JDBC 的批量处理语句包括下面三个方法:

    addBatch(String):添加需要批量处理的SQL语句或是参数;
    
    executeBatch():执行批量处理语句;
    
    clearBatch():清空缓存的数据
    

        通常我们会遇到两种批量执行 SQL 语句的情况:

        ① 多条 SQL 语句的批量处理;

        ② 一个 SQL 语句的批量传参;

    二、高效的批量插入

      1、举例:向数据表中插入 20000 条数据

        数据库中提供一个 goods 表,创建如下:

    create table goods (
      id int primary key auto_increment,
      name varchar(20)    
    );
    

      

      2、实现层次一:使用 Statement

        代码实现:

    1 Connection conn = JDBCUtils.getConnection();
    2 Statement st = conn.createStatement();
    3 for(int i = 1;i <= 20000;i++){
    4     String sql = "insert into goods(name) values('name_' + "+ i +")";
    5     st.executeUpdate(sql);
    6 }

      3、实现层次二:使用 PreparedStatement

        代码实现:

     1     @Test
     2     public void testInsert2() {
     3         Connection conn = null;
     4         PreparedStatement ps = null;
     5         try {
     6             
     7             long start = System.currentTimeMillis();
     8             
     9             conn = JDBCUtils.getConnection();
    10             String sql = "insert into goods(name)values(?)";
    11             ps = conn.prepareStatement(sql);
    12             for(int i = 1;i <= 20000;i++){
    13                 ps.setObject(1, "name_" + i);
    14                 
    15                 ps.execute();
    16             }
    17             
    18             long end = System.currentTimeMillis();
    19             
    20             System.out.println("花费的时间为:" + (end - start));//20000:83065
    21         } catch (Exception e) {
    22             e.printStackTrace();
    23         }finally{
    24             JDBCUtils.closeResource(conn, ps);
    25         }
    26     }

        使用 PreparedStatement 可以进行预编译语句的执行,在数据库服务端会把编译器编译后的语句缓存下来,那么下次调用时只有相同的预编译语句一样就不需再编译了,直接将参数传入语句中就会执行,效率得到了提升。

      4、实现层次三:使用Batch

        修改1:需要使用 addBatch() / executeBatch() / clearBatch() 的API;

        修改2:MySQL 服务器默认是关闭批处理的,我们需要通过一个参数,让MySQL开启批处理的支持。

    ?rewriteBatchedStatements=true 写在配置文件的url后面

    例如:url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true

      

        修改3:使用更新的 MySQL 驱动,驱动:mysql-connector-java-5.1.37-bin.jar

        代码实现:

     1     @Test
     2     public void testInsert3() {
     3         Connection conn = null;
     4         PreparedStatement ps = null;
     5         try {
     6             
     7             long start = System.currentTimeMillis();
     8             
     9             conn = JDBCUtils.getConnection();
    10             String sql = "insert into goods(name)values(?)";
    11             ps = conn.prepareStatement(sql);
    12             for(int i = 1;i <= 1000000;i++){
    13                 ps.setObject(1, "name_" + i);
    14                 
    15                 //1."攒"sql
    16                 ps.addBatch();
    17                 
    18                 if(i % 500 == 0){
    19                     //2.执行batch
    20                     ps.executeBatch();
    21                     
    22                     //3.清空batch
    23                     ps.clearBatch();
    24                 }
    25                 
    26             }
    27             
    28             long end = System.currentTimeMillis();
    29             
    30             System.out.println("花费的时间为:" + (end - start));//20000:83065 -- 565
    31         } catch (Exception e) {                                //1000000:16086
    32             e.printStackTrace();
    33         }finally{
    34             JDBCUtils.closeResource(conn, ps);
    35             
    36         }
    37         
    38     }

        通过Batch批处理的方式,可以先把SQL“收集”起来,等积攒到一定的条数,然后再让数据库执行,这样一来就可以有效的减少与数据库的交互操作(减少IO),再次对效率的提高。

      5、实现层次四:设置连接不允许自动提交数据

        上面的 Batch 操作,效率来说已经不错了,但是还可以进一步优化:

     1     @Test
     2     public void testInsert4() {
     3         Connection conn = null;
     4         PreparedStatement ps = null;
     5         try {
     6             
     7             long start = System.currentTimeMillis();
     8             
     9             conn = JDBCUtils.getConnection();
    10             
    11             //设置不允许自动提交数据
    12             conn.setAutoCommit(false);
    13             
    14             String sql = "insert into goods(name)values(?)";
    15             ps = conn.prepareStatement(sql);
    16             for(int i = 1;i <= 1000000;i++){
    17                 ps.setObject(1, "name_" + i);
    18                 
    19                 //1."攒"sql
    20                 ps.addBatch();
    21                 
    22                 if(i % 500 == 0){
    23                     //2.执行batch
    24                     ps.executeBatch();
    25                     
    26                     //3.清空batch
    27                     ps.clearBatch();
    28                 }
    29                 
    30             }
    31             
    32             //提交数据
    33             conn.commit();
    34             
    35             long end = System.currentTimeMillis();
    36             
    37             System.out.println("花费的时间为:" + (end - start));//20000:83065 -- 565
    38         } catch (Exception e) {                                //1000000:16086 -- 5114
    39             e.printStackTrace();
    40         }finally{
    41             JDBCUtils.closeResource(conn, ps);
    42         }
    43     }

        当把自动提交事务关闭后,会把所有的 SQL 都执行完毕之后再进行事务的提交,相当于上面的执行一部分就进行提交,效率也有所提高(可能并不是很明显)。

     

  • 相关阅读:
    Vue.js双向绑定的实现原理和模板引擎实现原理(##########################################)
    JavaScript:最烂与最火
    JSP九大内置对象和四种属性范围解读
    codevs1009
    hdu 4869 Turn the pokers (2014多校联合第一场 I)
    OpenGL——点的绘制(使用OpenGL来绘制可旋转坐标系的螺旋线)
    nodejs 批处理运行 app.js
    jquery更新后怎样在一个站点中使用两个版本号的jQuery
    vs连接mysql出错解决方法
    uva 10627
  • 原文地址:https://www.cnblogs.com/niujifei/p/15013077.html
Copyright © 2011-2022 走看看