美文网首页数据库MySQL
Mysql中使用流式查询避免数据量过大导致OOM

Mysql中使用流式查询避免数据量过大导致OOM

作者: 阿里加多 | 来源:发表于2017-07-19 21:13 被阅读635次

    一、前言

    java 中MySQL JDBC 封装了流式查询操作,通过设置几个参数,就可以避免一次返回数据过大导致 OOM。

    阿里巴巴长期招聘Java研发工程师p6,p7,p8等上不封顶级别,有意向的可以发简历给我,注明想去的部门和工作地点:1064454834@qq.com

    二、如何使用

    2.1 之前查询

    public void selectData(String sqlCmd) throws SQLException {
    
        validate(sqlCmd);
    
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
    
        try {
    
            
            conn = petadataSource.getConnection();
            stmt = conn.prepareStatement(sqlCmd);
            rs = stmt.executeQuery();
    
            try {
                while(rs.next()){
                    try {
                        System.out.println("one:" + rs.getString(1) + "two:" + rs.getString(2) + "thrid:" + rs.getString(3));
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            } finally {
                close(stmt, rs, conn);
    
            }
    }
    

    2.2 现在流式查询

    public void selectData(String sqlCmd,) throws SQLException {
    
        validate(sqlCmd);
    
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
    
        try {
    
            conn = petadataSource.getConnection();
            
            stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
                stmt.setFetchSize(Integer.MIN_VALUE);
                
            rs = stmt.executeQuery();
    
            try {
                while(rs.next()){
                    try {
                        System.out.println("one:" + rs.getString(1) + "two:" + rs.getString(2) + "thrid:" + rs.getString(3));
                    } catch (SQLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            } finally {
                close(stmt, rs, conn);
    
            }
    }
    

    可知只是prepareStatement时候改变了参数,并且设置了PreparedStatement的fetchsize为Integer.MIN_VALUE。

    三、 结果对比

    对于同一个sqlCmd,同一批数据,使用两种方式占用内存对比如下:

    • 非流式编程


      image.png
    • 流式编程


      image.png

    另外非流式方式由于是把符合条件的数据一下子全部加在到内存,并且由于数据量比较大,需要mysql处理的时间比较长,我测试情况下需要一分钟才会返回结果到内存(数据量比较大),然后才能通过数据集返回数据。

    而流式方式是每次返回一个记录到内存,所以占用内存开销比较小,并且调用后会马上可以访问数据集的数据。

    想获取更多阿里ATA干货,请关注微信公众号:‘技术原始积累’

    image.png

    相关文章

      网友评论

      • 吴玉_ef21:直接用mybatis 自带的Cursor 做返回值更简单

      本文标题:Mysql中使用流式查询避免数据量过大导致OOM

      本文链接:https://www.haomeiwen.com/subject/wwjrkxtx.html