Построить Jooq поток слишком медленно

Я использую Scala.

Я попытался получить все данные из таблицы с 4 миллионами строк. Я использовал поток и код похож

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

Выражение SelectFinalStep[Запись] в Jooq.

Однако первая строка слишком медленная. Это стоит минут. Я делаю что-то неправильно?

2 ответа

Используйте Stream API напрямую

Если вы используете Scala 2.12, вам не нужно преобразовывать поток Java, возвращаемый expression.stream() Скала Iterator а потом в скалу Stream, Просто позвоните:

expression.stream().forEach(println);

В то время как JOOQ ResultQuery.stream() метод создает ленивый Java 8 Stream, который отбрасывается снова после употребления, Scala's Stream сохраняет ранее извлеченные записи в памяти для повторного прохождения. Это, вероятно, то, что вызывает большинство проблем с производительностью, при получении 4 миллионов записей.

Примечание о ресурсах

Обратите внимание, что expression.stream() возвращает находчивый поток, сохраняя открытый ResultSet а также PreparedStatement, Возможно, это хорошая идея, чтобы явно закрыть поток после потребления.

Оптимизировать размер выборки JDBC

Кроме того, вы можете посмотреть на звонки expression.fetchSize(), который обращается к JDBC Statement.setFetchSize(), Это позволяет драйверу JDBC извлекать пакеты из N строк. Некоторые драйверы JDBC по умолчанию имеют разумный размер выборки, другие по умолчанию загружают все строки в память перед передачей их клиенту.

Другим решением было бы лениво извлекать записи и создавать поток 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()
}
Другие вопросы по тегам