mysql大結果集保存到es處理方法


轉自:https://blog.csdn.net/seven_3306/article/details/9303879

 

---  避免出現oom

在處理mysql數據同步到es上時遇到的問題和解決方案:

最初在使用的是JPA數據連接處理,先分頁查詢出數據,然后在轉成ES需要的數據格式

這里用的是最low的JSON轉換

JSONArray.parseArray(JSON.toJSONString(list),Object.class)

然后在保存到es中,此處的弊端:

  1.讀取mysql的list緩存在內存中,在通過json轉換,太耗內存

  2.mysql讀取方式使用limit分頁,查詢效率低下

 

針對第二點可以優化:(避免使用limit 20000,1000,因為使用limitmysql會掃描前20000后開始往后取1000)

  如果id的int或long型,且唯一

  查詢sql可以通過id排序(這里使用的是正序),第一次取id>0,其后每次的條件都是id>取出最后一個對象的id,然后使用limit 0,1000結尾

 

但是如果使用mysql的jdbc fetch的流數據接收方式,就可以一次查詢億萬條數據,不會在連接上耗費太多時間

PreparedStatement preparedStatement = jdbcTemplate.getDataSource().getConnection().prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
//這里設置成50000是不生效的 preparedStatement.setFetchSize(Integer.MIN_VALUE); preparedStatement.setFetchDirection(ResultSet.FETCH_REVERSE); ResultSet resultSet
= preparedStatement.executeQuery(); List rs = new ArrayList(); while (resultSet.next()) {   UserEs userEs = new UserEs(); userEs .setId(resultSet.getInt("id")); rs.add(anchorEs); if(rs.size()>=50000){   es.saveAll(rs); rs = new ArrayList(); } }

最后這個方法就規避了mysql查詢出來數據與es存儲對象轉換的問題

 

 

jdbcTemplate.query(connection ->{
                PreparedStatement preparedStatement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
                preparedStatement.setFetchSize(Integer.MIN_VALUE);
                preparedStatement.setFetchDirection(ResultSet.FETCH_REVERSE);
                return preparedStatement;
            },resultSet-> {
          List rs = new ArrayList();
          while (resultSet.next()) {
          UserEs userEs = new UserEs();
           userEs .setId(resultSet.getInt("id"));
           rs.add(anchorEs);
           if(rs.size()>=50000){
             es.saveAll(rs);
              rs = new ArrayList();
           }
        }    
     });

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM