web-dev-qa-db-ja.com

ResultSetはすべてのデータをメモリにロードしますか、それとも要求されたときだけロードしますか?

Oracleデータベースのレコードを表示するGUIテーブルがある.jspページがあります。このテーブルでは、「FIRST」、「NEXT」、「PREVIOUS」、「LAST」などの典型的なページネーション動作が可能です。レコードは、SQLステートメントの実行から返されるJava ResultSetオブジェクトから取得されます。

このResultSetは非常に大きい可能性があるため、私の質問は次のとおりです。

100万件のレコードを含むResultSetがあるが、テーブルにResultSetの最初の10件のレコードからのデータしか表示されない場合、データは、レコードデータのリクエストを開始したときにのみフェッチされるか、またはResultSetの後にすべてのデータが完全にメモリにロードされます。 SQLステートメントの実行から返されますか?

35
tth

Java ResultSetは、データベース内の結果へのポインタ(またはカーソル)です。ResultSetは、データベースからブロック単位でレコードをロードします。そのため、質問に答えるために、データは要求されたときにのみフェッチされますそれはブロックです。

ドライバーが一度にフェッチする行数を制御する必要がある場合は、ResultSetで setFetchSize(int rows) メソッドを使用できます。これにより、一度に取得するブロックの大きさを制御できます。

42
Chris Dail

JDBC仕様では、データがストリーミングされるかどうか、またはメモリにロードされるかどうかは指定されていません。 Oracleはデフォルトでストリーミングします。 MySQLではサポートしていません。 MySQLに結果セットをストリーミングさせるには、ステートメントに以下を設定する必要があります。

    pstmt = conn.prepareStatement(
        sql,
        ResultSet.TYPE_FORWARD_ONLY,
        ResultSet.CONCUR_READ_ONLY);
    pstmt.setFetchSize(Integer.MIN_VALUE);
11
Joshua

JDBC仕様では、結果セットのすべてのデータがフェッチされるかどうかは指定されていませんが、適切に作成されたドライバーはフェッチしません。

とはいえ、スクロール可能な結果セットは、あなたが考えている以上のものになる可能性があります:(リンクは編集され、スパイウェアページを指しています)

セッションに格納されている、切断された行セットを検討することもできます(サイトのスケーラビリティの必要性に応じて): http://Java.Sun.com/j2se/1.4.2/docs/api/ javax/sql/RowSet.html

1

最良のアイデアは、サブクエリを作成し、一度に、または単一のページに100または1000行を表示することです。そして、接続プーリングによって接続を管理します。

サブクエリを作成するには、Oracleでは行数を、MY SQLでは制限を使用できます。

0
Tony

500レコードを含むテーブルがあるとしましょう

PreparedStatement stm=con.prepareStatement("select * from table");
stm.setFetchSize(100);// now each 100 records are loaded together from the database into the memory,
// and since we have 500 5 server round trips will occur.
ResultSet rs = stm.executeQuery();
rs.setFetchSize (50);//overrides the fetch size provided in the statements,
//and the next trip to the database will fetch the records based on the new fetch size
0
QuakeCore