【问题标题】:Read / process resultsets parallel in java在java中并行读取/处理结果集
【发布时间】:2017-03-05 04:40:24
【问题描述】:

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

while(rs.next()) {
    System.out.println(rs.getString(1));
    }

使用流和拆分器:

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);

记录总数:3759
顺序花费的时间:~ 83.8 秒
Streams 花费的时间:~ 83.5 秒

谁能查看这个并告诉我我是否没有正确实现流。

【问题讨论】:

  • 也许这个问题和答案会有所帮助:stackoverflow.com/a/32232173/4105457
  • 我在连接您的标题和问题时遇到了问题。
  • 结果集处理示例太多了,我猜你的问题出在其他地方?我认为您应该能够使您的问题更加具体。目前,我认为答案还不清楚。
  • @Flown 早些时候,我确实尝试了您在上面建议的 SO 参考中给出的解决方案。但这并没有带来任何性能提升。用我尝试过的代码和结果更新了 OP。
  • 请注意,如果您使用开源数据库,jOOQ 是免费的。并行处理对流有一些开销,并且 JDBC 驱动程序将执行大量同步以使连接线程安全,这可能会使您的代码串行化;您可能需要考虑在单个线程上从数据库中检索值,然后才将其并行化。

标签: java jdbc java-8 java-stream resultset


【解决方案1】:

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

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

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

【讨论】:

  • :( 好吧,这让我对我现在拥有的任何解决方案都感到痛苦。我仍然会保持这个问题的开放性,看看是否有人能够提出任何黑客/解决方法。但感谢您的回复和解释.
  • 但是,您可以打开多个 JDBC 连接并将查询拆分为多个独立的查询,然后您可以并行执行这些查询。一些实验很可能让您达到数据库或网络连接成为瓶颈的地步。
  • @ThorbjørnRavnAndersen 进入“让数据库做尽可能多的事情”的方向,因为这意味着数据库负责将数据拆分成块(如果不是程序员能够将其拆分)单个查询语句甚至在此之前变成多个 不同 语句)。除非您拥有其中一个非常大的分布式数据库系统,否则创建多个语句(甚至多个连接)会比整个批量数据传输操作产生更多开销。
  • @Holger 也许吧。取决于实际使用情况,但由于 OP 想要获得更好的性能,所以这里的方法是并行并拆分工作。
猜你喜欢
  • 2020-05-19
  • 1970-01-01
  • 2015-10-24
  • 1970-01-01
  • 2011-07-03
  • 2023-04-07
  • 2015-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多