在java中并行读取/处理结果集

Mru*_*sar 2 java jdbc resultset java-8 java-stream

我有这个要求迭代结果集中返回的数百万条记录并处理它们并将它们存储在某些数据结构中。我找不到任何相关的例子或参考。JOOQ 似乎在做一些我可能想要的事情,但它似乎不是免费的。我希望如果使用 java 8 流我可能能够实现它,但不是 example 或 writeup 似乎给了我任何前进的方向。我也对其他选择持开放态度。
基于这个 SO 参考:resultset parallel我在下面尝试过,但它没有给我任何性能改进,如下面的性能指标所示。
代码:顺序迭代:

while(rs.next()) {
    System.out.println(rs.getString(1));
    }
Run Code Online (Sandbox Code Playgroud)

使用流和拆分器:

Stream<String> s = StreamSupport.stream(new Spliterators.AbstractSpliterator<String>(Long.MAX_VALUE,
                Spliterator.ORDERED) {

            @Override
            public boolean tryAdvance(Consumer<? super String> action) {
                try {
                    if (!rs.next())
                        return false;
                    action.accept(rs.getString(1));
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return true;
            }
        }, true);
        s.forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

记录总数:3759
Sequential 花费的时间:~83.8 secs
Streams 花费的时间:~83.5 secs

任何人都可以查看并告诉我我是否没有正确实现流。

Hol*_*ger 7

AResultSet不能并行处理。它是一种迭代器,包含必须为查询更改的可变状态,最值得注意的是,在ResultSet读取之前必须将其移动到当前行。即使对于通过索引访问的行中的值,规范也没有提供线程安全保证,并提到底层数据库可能不支持乱序读取它们的可能性。

因此,唯一可以从并行处理中受益的操作是链式后续操作,但是当唯一的链式操作是 a 时System.out::println,情况会变得更糟。不仅打印操作不能从并行处理中受益,所有标准实现都有一个PrintStreaminSystem.out将每个写操作同步到目标输出。

请注意,即使您链接可能受益于并行处理的计算密集型操作,昂贵的数据库操作仍有可能支配整个执行时间。这就是为什么在将数据传输到 Java 端之前,让数据库尽可能多地过滤和/或聚合数据很重要的原因……