构建Jooq流太慢了

时间:2017-06-21 05:52:26

标签: scala stream jooq

我正在使用Scala。

我尝试从大约400万行的表中获取所有数据。我使用了流,代码就像

val stream Stream[Record] = expression.stream().iterator().asScala.toStream
stream.map(println(_))

表达是Jooq中的SelectFinalStep [Record]。

然而,第一行太慢了。它需要几分钟。我做错了吗?

2 个答案:

答案 0 :(得分:2)

直接使用Stream API

如果您使用的是Scala 2.12,则不必将expression.stream()返回的Java流转换为Scala Iterator,然后转换为Scala Stream。只需致电:

expression.stream().forEach(println);

虽然jOOQ的ResultQuery.stream()方法创建了一个懒惰的Java 8 Stream,它在消费后再次被丢弃,但Scala的Stream会将先前获取的记录保留在内存中以便重新遍历。在获取400万条记录时,这可能是造成大多数性能问题的原因。

关于资源的说明

请注意expression.stream()会返回一个资源丰富的流,保持一个开放的基础ResultSetPreparedStatement。也许,在消费后明确关闭流是个好主意。

优化JDBC提取大小

此外,您可能希望调用调用expression.fetchSize()Statement.setFetchSize()来调用JDBC的{{3}}。这允许JDBC驱动程序获取N行批次。某些JDBC驱动程序默认使用合理的提取大小,其他驱动程序默认在将所有行传递到内存之前将其提取到内存中。

答案 1 :(得分:0)

另一种解决方案是延迟获取记录并构造一个scala流。例如:

def allRecords():Stream[Record] = {
  val cur = expression.fetchLazy()
  def inner(): Stream[Record] = {
    if(cur.hasNext) {
      val next =  cur.fetchOne
      next #:: inner()
    }
    else
      Stream.empty
    }
  inner()
}