私はPayara 4.1(Eclipselink 2.6)、Postgres 9.6を使用しています。PostgresのPayara/EclipseLinkのScrollableCursorのメモリの問題
私はScrollableCursorを使ってかなり大きなデータ結果にアクセスしようとしています。テストでは、クエリを実行しようとしているjava.lang.OutOfMemoryErrorを取得していましたので、少量のデータでヒープダンプのトラブルシューティングを行い、ArrayListの行のorg.postgresql.jdbc.PgResultSetで多くのメモリを検出しました。
EclipseLink documentationに基づいて、ScrollableCursorを取得するためのヒントを提供していますが、Postgres JDBCドライバのソースコードを添付してデバッグした後、フェッチサイズを設定しなかった場合は、そこでQueryHints.JDBC_FETCH_SIZEを追加しました。しかし、私はそれがまだ全体のクエリ結果をフェッチし、それらを最初にメモリに保存していることを発見しています。
org.postgresql.v3.QueryExecutorImpl sendOneQueryでは、QUERY_FORWARD_CURSORフラグが設定されている場合にのみ、初期ローをフェッチサイズに設定します。
org.postgresql.jdbc.PgStatement executeInternalフェッチサイズがあり、結果セットがスクロール可能でなく、接続がautoCommitでなく、結果セットが保持できない場合にのみ、QUERY_FORWARD_CURSOR flageを設定します。私の接続をデバッグするとき
は、私は別の@StatelessのEJB内の別の@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)メソッドから呼び出されたEJB @Statelessに@TransactionAttribute(TransactionAttributeType.REQUIRED)から呼んでいるにもかかわらず、自動コミットするように設定されています。
私のクエリが自動接続にデフォルトの新しい接続を使用しているように見える理由はわかりません。 QueryHints.READ_ONLYを使用する前は非トランザクションなので、おそらく新しい接続を使用していましたが、削除しました。他のクエリのヒントの1つが新しい接続を引き起こしていますか?私が使用すべき追加のヒントはありますか? Payara/EclipselinkとPostgresのバグがありますので、ScrollableCursorを使用すると実際にはスクロールしませんか?
private static <T> void executeScrollableQuery(@NotNull final Query query, final Consumer<T> recordConsumer) {
query.setHint(QueryHints.RESULT_SET_TYPE, ResultSetType.ForwardOnly)
.setHint(QueryHints.SCROLLABLE_CURSOR, HintValues.TRUE)
.setHint(QueryHints.MAINTAIN_CACHE, HintValues.FALSE).setHint(QueryHints.JDBC_FETCH_SIZE, 500);
ScrollableCursor cursor = null;
try {
cursor = (ScrollableCursor) query.getSingleResult();
while (cursor.hasNext()) {
recordConsumer.accept((T) cursor.next());
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}