Oracle操作批量入库 执行效率

本文探讨了在Java中使用不同方法进行大规模数据插入的性能对比,包括JPA的persist方法、PreparedStatement与批处理技术。通过实验,展示了批处理技术在处理大量数据时的显著优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

不管三七二十一

 

 

/**
 * Created by Administrator on 2019/1/12.
 * 描述: 批量入库的持久化方法实现类
 *
 * @author Young
 * @create 2019-01-12 20:06
 */
@Repository
public class BaseDaoImpl<T, ID extends Serializable> implements BaseDao<T, ID> {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @PersistenceContext
    private EntityManager entityManager;

    @Transactional(readOnly = true)
    @Override
    public void save(List<T> entityList) {
        int size = entityList.size();
        logger.debug("获取到执行的数据是size:" + size);
        for (int i = 0; i < size; i++) {
            entityManager.persist(entityList.get(i));
            if (i % 500 == 0 || i == (size - 1)) {
                entityManager.flush();
                entityManager.clear();
            }
        }
        logger.debug("执行结束数据的size:" + size);
    }
}
/**
 * Created by Administrator on 2019/1/12.
 * 描述: 持久层的接口方法
 *
 * @author Young
 * @create 2019-01-12 20:05
 */
public interface BaseDao<T,ID extends Serializable> {
    /**
     * 保存数据对象
     * @param entityList
     * @return
     */
    void save(List<T> entityList);
}

 

一开始使用的jpa的crud的save方法.每次save之前都要select一下,效率低下....

换peisist后,效率是生了...1s 4000左右,但是还是太少了...烦....

 

 

但看了大佬们用的批处理的方式,虽然不是使用jpa的,但是效率如果可以起来的话,未尝不可,所以还是先马了....然后再仔细分析

 

https://www.ablanxue.com/prone_13223_1.html  大佬的

java自带的批量操作,就可以很好的支持大量数据的处理。相比c#,简单很多。c#要使用oracle提供的ODP.NET,效率才很高,但是代码却很复杂。总之,在这方面,c#没得比。当然,这里的表是没加索引的,加了索引,效率会变慢,但是还是很高效。

long startTime=System.currentTimeMillis();
        
        Connection conn=null;
        try{
            conn=getConnection();
            conn.setAutoCommit(false);
            
            PreparedStatement stmt=conn.prepareStatement("INSERT INTO product_tmp VALUES (?,?,?,?)");
            System.out.println("数据大小:"+datas.size());        //1000000

            int num=0;
            for(Values v:datas){
                num++;
                stmt.setInt(1, v.getId());
                stmt.setString(2, v.getStr1());
                stmt.setString(3, v.getStr2());
                stmt.setString(4, v.getStr3());
                stmt.addBatch();
                //注意: 每5万,提交一次;这里不能一次提交过多的数据,我测试了一下,6万5000是极限,6万6000就会出问题,插入的数据量不对。
                if(num>50000){
                    stmt.executeBatch();
                    conn.commit();
                    num=0;
                }
            }
            stmt.executeBatch();
            conn.commit();
        }catch(Exception e){
            conn.rollback();
            e.printStackTrace();
        }finally{
            closeConnection(conn);
            long endTime=System.currentTimeMillis();
            System.out.println("方法执行时间:"+(endTime-startTime)+"ms");
        }

 

另外一个大佬的,是做个总结

https://blog.youkuaiyun.com/liuxigiant/article/details/16939505   大佬,墙裂推荐

使用jdbc向数据库插入100000条记录,分别使用statement,PreparedStatement,及PreparedStatement+批处理3种方式进行测试: 

 

public void exec(Connection conn){    
  try {    
   //开始时间   
   Long beginTime = System.currentTimeMillis();    
   //设置手动提交    
   conn.setAutoCommit(false);   
       
   Statement st = conn.createStatement();    
  
   for(int i=0;i<100000;i++){    
      String sql="insert into t1(id) values ("+i+")";    
      st.executeUpdate(sql);     
   }    
      
   //结束时间   
   Long endTime = System.currentTimeMillis();    
  
   System.out.println("st:"+(endTime-beginTime)/1000+"秒");//计算时间    
  
   st.close();    
   conn.close();    
  } catch (SQLException e) {    
   e.printStackTrace();    
  }     
}  

//2.使用PreparedStatement对象 


public void exec2(Connection conn){    
  try {    
   Long beginTime = System.currentTimeMillis();    
   conn.setAutoCommit(false);//手动提交    
   PreparedStatement pst = conn.prepareStatement("insert into t1(id) values (?)");    
   for(int i=0;i<100000;i++){    
    pst.setInt(1, i);    
    pst.execute();       
   }    
   conn.commit();    
   Long endTime = System.currentTimeMillis();    
   System.out.println("pst:"+(endTime-beginTime)/1000+"秒");//计算时间    
   pst.close();    
   conn.close();    
  } catch (SQLException e) {    
   e.printStackTrace();    
  }    
  
}  

 

//3.使用PreparedStatement + 批处理 


public void exec3(Connection conn){    
  try {    
   conn.setAutoCommit(false);    
   Long beginTime = System.currentTimeMillis();    
   //构造预处理statement   
   PreparedStatement pst = conn.prepareStatement("insert into t1(id) values (?)");    
   //1万次循环   
   for(int i=1;i<=100000;i++){       
    pst.setInt(1, i);    
    pst.addBatch();    
    //每1000次提交一次   
    if(i%1000==0){//可以设置不同的大小;如50,100,500,1000等等    
     pst.executeBatch();    
     conn.commit();    
     pst.clearBatch();    
    }    
   }   
   Long endTime = System.currentTimeMillis();    
   System.out.println("pst+batch:"+(endTime-beginTime)/1000+"秒");    
   pst.close();    
   conn.close();    
  } catch (SQLException e) {    
   e.printStackTrace();    
  }    
}   

在Oracle 10g中测试,结果: 
1.使用statement  耗时142秒; 
2.使用PreparedStatement 耗时56秒; 
3.使用PreparedStatement + 批处理耗时: 
   a.50条插入一次,耗时5秒; 
    b.100条插入一次,耗时2秒; 
    c.1000条以上插入一次,耗时1秒; 
通过以上可以得出结论,在使用jdbc大批量插入数据时,明显使用第三种方式(PreparedStatement + 批处理)性能更优。

 

普通方式处理大量数据的insert时,处理速度相当慢。   
*/   
PreparedStatement ps = null;   
//循环10000次   
for(int i = 0; i < 100000; i++) {   
    ps = con.prepareStatement(sql);   
    ps.executeUpdate();   
}  
/**方法二:通过addBatch()的方式,将数据缓存在对象里面,通过最后执行executeBatch();方法提交,因此*速度会快很多!   
*/   
PreparedStatement ps = con.prepareStatement(sql);   
for(int i = 0; i < 100000; i++) {   
    ps.setString(1, "1");   
    ps.setString(2, "2");   
    ps.addBatch();   
}   
ps.executeBatch(); 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值