1

私はこのコードを持っています。このコードは基本的にPreparedStatementテーブルデータ全体のロードを避けるために制限を設定しています。

PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
        pstmt = con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
        if (getDataSheet().isPagingEnabled()) {
            pstmt.setFetchSize(getDataSheet().getPageSize() + 1);
        }

        if (getDataSheet().isDisableTotalRowsCount() && maxRecords >= 0) {
            if (getDataSheet().isPagingEnabled()) {
                pstmt.setMaxRows(getCurrentPageSize());
            } else {
                pstmt.setMaxRows(maxRecords);
            }
        }

        //the rest of code.

    } catch(Exception ex) {
        //handle exception
    }

このコードは、すべての DB ベンダーで正常に動作します。ただし、Oracle ドライバーで を使用した 1 つのケースを除きsetFetchSizePreparedStatementページ サイズが 20000 を超えていた場合、ドライバーは OutOfMemoryError をスローします。

Caused by: java.lang.OutOfMemoryError: Java heap space
at oracle.jdbc.driver.PhysicalConnection.getCharBuffer(PhysicalConnection.java:7018)
at oracle.jdbc.driver.OracleStatement.prepareAccessors(OracleStatement.java:907)
at oracle.jdbc.driver.T4CTTIdcb.receiveCommon(T4CTTIdcb.java:261)
at oracle.jdbc.driver.T4CTTIdcb.receive(T4CTTIdcb.java:127)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:992)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:194)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:791)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:866)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1186)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3387)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3431)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1203)

なぜOracleでそれが起こっているのですか?DBレベルでやるべきことはありますか? ありがとうございます。

4

1 に答える 1

6

あなたの考えに反して、setFetchSizeは取得するレコードの量を制限せず、ドライバーがプリフェッチしてキャッシュする必要があるレコードの数を決定 (またはヒント) します。例外は MySQL で、フェッチ サイズを に設定しない限り、常にすべてのレコードをプリフェッチしますInteger.MIN_VALUE

ドライバーは、メモリが使い果たされるほど多くの行を取得しているだけです。

于 2014-01-16T10:43:10.723 に答える