美文网首页
JDBC读取mysql的数据的效率问题

JDBC读取mysql的数据的效率问题

作者: 早点起床晒太阳 | 来源:发表于2020-05-14 14:35 被阅读0次

背景

这边我们做了一个产品的小功能,把mysql的数据拉取到hdfs上来

代码实现

代码很简单,就是简单的JDBC

long start = System.currentTimeMillis();
PreparedStatement preparedStatement = connection.prepareStatement("select * from ceshi");
ResultSet resultSet = preparedStatement.executeQuery();
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
long end = System.currentTimeMillis();
System.out.println("------"+Thread.currentThread()+"获取数据消耗时间"+(end-start)/1000);

读取数据,然后hdfs的IO流写入到hdfs上面。但是我发现在读取数据的时候会出现卡顿的情况。(我这边数据量大约100W),我打印了日志,发现在接收数据的时候,耗时大约在10秒,
后来开始查资料发现mysql查询的机制是jdbc默认的读取数据的时候,会将要查询的数据一次性读到内存中,再通过resultSet循环读取出来。

调研了下发现可以通过JDBC 流的方式来读取数据,这种方式可以将读取出来的每一条数据查询到客户端,再执行insert操作,这样机器负载就会轻很多。
相关源码如下

    /**
     * We only stream result sets when they are forward-only, read-only, and the
     * fetch size has been set to Integer.MIN_VALUE
     * 
     * @return true if this result set should be streamed row at-a-time, rather
     *         than read all at once.
     */
    protected boolean createStreamingResultSet() {
        return ((this.query.getResultType() == Type.FORWARD_ONLY) && (this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY)
                && (this.query.getResultFetchSize() == Integer.MIN_VALUE));
    }

然后之前的代码如下

long start = System.currentTimeMillis();
PreparedStatement preparedStatement = connection.prepareStatement("select * from ceshi",ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
preparedStatement.setFetchSize(Integer.MIN_VALUE);
ResultSet resultSet = preparedStatement.executeQuery();
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
long end = System.currentTimeMillis();
System.out.println("------"+Thread.currentThread()+"获取数据消耗时间"+(end-start)/1000);

然后就会发现获取数据不会消耗时间,大大提升了效率。
顺便说一下 不添加 这两个参数ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY 也可以,因为mysql connection.prepareStatement(sql)中就默认设置这两个参数的。感兴趣的可以直接看下源码。
所以为了方便也可以直接设置

preparedStatement.setFetchSize(Integer.MIN_VALUE);

参考资料:https://blog.csdn.net/zhouxukun123/article/details/83476715

相关文章

网友评论

      本文标题:JDBC读取mysql的数据的效率问题

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