Построить 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()
}