flybar0015
flybar0015
2011-05-12 15:18
浏览 1.2k
已采纳

spring jdbctemplate batch 可以处理多少条记录

[code="java"]
//1、统计一共多少数据
int countNum = jdbcTamplate1.queryForInt("select count(0) from tabA") ;

    System.out.println("总记录条数为:"+countNum);

    int l = (countNum + 29999) / 30000 ;

    jdbcTamplate2.getDataSource().getConnection().setAutoCommit(false) ;

    for(int i=0; i<l; i++){

        int startRowNum = i * 30000 ;
        int endRowNum = (i+1) * 30000 ;
        if(i == l-1){
            endRowNum = countNum ;
        }

        //构造查询语句
        StringBuilder sql = new StringBuilder() ;
        sql.append("select ID, X, Y, from (") ;
        sql.append("select rownum r, ID, X, Y from tabA where rownum <= ") ;
        sql.append(endRowNum + " ") ;
        sql.append("order by ID asc) ") ;
        sql.append("where r > ") ;
        sql.append(startRowNum) ;

        List<Map<String, Object>> rs = jdbcTamplate1.queryForList(sql.toString()) ;             
        System.out.println((i+1)+"[]获得结果集记录数:"+rs.size());

        int[] ns = jdbcTamplate1.batchUpdate(Locrecord.INSERT_SQL, new LocrecordBatchSetter(rs)) ;

        System.out.println((i+1)+"[]本次batch记录数:"+ns.length);

        jdbcTamplate1.getDataSource().getConnection().commit() ;            

        Thread.sleep(10000) ;

        System.out.println((i+1)+"[]本次循环结束!");
    }

    jdbcTamplate1.getDataSource().getConnection().setAutoCommit(true) ;

    [/code]

其中,Locrecord.INSERT_SQL这个就是简单的insert语句,只插入3个字段,后边的这个LocrecordBatchSetter

也很简单,就是把新表的字段和旧表的字段对应上。比如:
[code="java"]
public void setValues(PreparedStatement pstmt, int i) throws SQLException {

Map<String, Object> obj = list.get(i) ;

pstmt.setString(1, obj.get("ID")+"") ;
pstmt.setInt(2, (obj.get("X")) ;
pstmt.setInt(3, obj.get("Y")) ;

}
[/code]

我是从一个库的表A导数据到另一个库的表B,他们的表结构不一样,只是提出部份可以匹配的字段。

原表有数据73W,我每次导入3W,可是每次循环到21W数据的时候程序就没反应了。也不抛任何异常。控制台显示程序还在进行。

去数据库一看,只有21W数据进入,剩下的就没戏了。想问问用过batch插入的兄弟们。你们碰见过这样的情况吗?
应该如何解决呢?或者使用batch时,还应该注意哪些事情?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

11条回答 默认 最新

  • redstarofsleep
    redstarofsleep 2011-05-13 15:36
    已采纳

    第8行和第34行拿到的是同一个connection吗?

    第8行拿了把它放个变量里吧,下面直接操作这个connection
    Conncetion conn = jdbcTamplate2.getDataSource().getConnection()

    还有个问题,为什么第8行是jdbcTamplate2其它是jdbcTamplate1

    点赞 评论
  • iihero
    iihero 2011-05-12 15:20

    每次3W太大了,每次2000吧。

    点赞 评论
  • redstarofsleep
    redstarofsleep 2011-05-12 15:22

    再改小一点吧。
    多少条记录也没有个一定的,根据单条记录的数据量来看,如果一条记录数据量就很多,那么一次能处理的就少一点。

    点赞 评论
  • guoqingcun
    月亮床 2011-05-12 16:29

    为什么会这现这种问题呢?原因是什么,怎么理解呢?

    点赞 评论
  • iihero
    iihero 2011-05-13 06:27

    针对每次提交,事务日志要记录这次提交的所有操作,包括数据,30000太大了,可能事务日志空间已满。

    点赞 评论
  • redstarofsleep
    redstarofsleep 2011-05-13 09:16

    [quote]那不一样么?我一共73W数据,都要写事务日志。

    从日志记录上来说,一次3W和一次3条有什么不同么?

    最终不都是得写73W数据的日志? [/quote]

    应该是临时空间不够用了,一次事务提交后会释放临时空间的。

    点赞 评论
  • iihero
    iihero 2011-05-13 09:47

    [quote]那不一样么?我一共73W数据,都要写事务日志。

    从日志记录上来说,一次3W和一次3条有什么不同么?

    最终不都是得写73W数据的日志? [/quote]

    一次3W,必须有3W条对应的可用日志空间,建议你看看redo log相关的资料。

    点赞 评论
  • redstarofsleep
    redstarofsleep 2011-05-13 13:12

    [quote]关于事务,我是循环一次就提交一次啊。也就是说每3W条记录提交一次事务。

    那这个临时空间不就释放了么? [/quote]
    一个事务里做3W条,太多了,临时空间也需要3W条这么多。
    还是改少一点吧

    点赞 评论
  • iihero
    iihero 2011-05-13 13:18

    [quote]关于事务,我是循环一次就提交一次啊。也就是说每3W条记录提交一次事务。

    那这个临时空间不就释放了么? [/quote]

    提交了事务,只是保证有一个checkpoint,但是日志中的数据并不一定马上写回数据文件。

    为什么不看看数据库服务器上的消息日志文件呢?

    点赞 评论
  • redstarofsleep
    redstarofsleep 2011-05-13 14:09

    把每次3W条改成每次1W条

    点赞 评论
  • iihero
    iihero 2011-05-13 18:55

    有一个值得怀疑的地方,
    几处connection,未必是同一个connection,先用同一个connection 试试。

    点赞 评论

相关推荐