You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Oracle JDBC驱动一次性获取全部数据行

优化大结果集JDBC查询性能:从3秒到0.7秒的实践

最近我处理了一个JDBC查询性能的问题,分享下我的解决过程:

问题背景

我有一个数据库查询会返回约6000行数据,需要把所有数据行取出来,用来生成执行批处理任务的R脚本。最开始用的常规方法耗时3秒,客户反馈这个速度太慢了。

旧方案(耗时3秒)

我一开始的实现是执行查询后,遍历ResultSet逐条把数据填充到ArrayList里,精简后的代码大概是这样:

public List<MyClass> loadFromDB() throws SQLException {
    List<MyClass> resultList = new ArrayList<>();
    String sql = "SELECT col1, col2, ... FROM my_table WHERE ...";
    try (Connection conn = getConnection();
         PreparedStatement stmt = conn.prepareStatement(sql);
         ResultSet rs = stmt.executeQuery()) {
        while (rs.next()) {
            MyClass item = new MyClass();
            item.setCol1(rs.getString("col1"));
            // 其他字段赋值
            resultList.add(item);
        }
    }
    return resultList;
}

优化方案(耗时0.7秒)

我调整了两步操作,直接把性能提上去了:

  • 第一步:先执行一个计数查询,拿到结果集的总行数:SELECT COUNT(*) FROM my_table WHERE ...
  • 第二步:在创建PreparedStatement的时候,调用stmt.setFetchSize(totalRows),把Fetch Size设置为结果集的总条数,这样JDBC会一次性从数据库拉取所有数据,减少了多次网络交互的开销

优化后的核心代码片段:

// 先获取总行数
int totalRows = 0;
String countSql = "SELECT COUNT(*) FROM my_table WHERE ...";
try (Connection conn = getConnection();
     PreparedStatement countStmt = conn.prepareStatement(countSql);
     ResultSet countRs = countStmt.executeQuery()) {
    if (countRs.next()) {
        totalRows = countRs.getInt(1);
    }
}

// 再执行查询并设置Fetch Size
List<MyClass> resultList = new ArrayList<>(totalRows); // 提前初始化容量,小幅度优化性能
String dataSql = "SELECT col1, col2, ... FROM my_table WHERE ...";
try (Connection conn = getConnection();
     PreparedStatement dataStmt = conn.prepareStatement(dataSql)) {
    dataStmt.setFetchSize(totalRows); // 关键优化点
    try (ResultSet rs = dataStmt.executeQuery()) {
        while (rs.next()) {
            MyClass item = new MyClass();
            item.setCol1(rs.getString("col1"));
            // 其他字段赋值
            resultList.add(item);
        }
    }
}
return resultList;

为什么这个优化有效?

默认情况下,JDBC的Fetch Size通常很小(不同数据库默认值不同,比如Oracle是10,MySQL默认是100),这意味着每次只会从数据库拉取少量数据,需要多次和数据库建立网络连接、传输数据,这在数据量较大时会产生明显的开销。把Fetch Size设置为结果集的总条数,就能一次性拉取所有数据,大幅减少网络往返次数,从而显著提升查询性能。

内容的提问来源于stack exchange,提问作者Dan Newman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:05:28