私は毎日何百万ものレコードを含む非常に大きなテーブルを持っており、毎日の終わりに前日からすべてのレコードを取得します。これが私のやり方です:
String SQL = "mytable からcol1、col2、coln を選択します (timecol = Yesterday)"; Statement.executeQuery(SQL);
問題は、このプログラムはすべての結果をメモリに格納してから処理するため、約 2 GB のメモリを必要とすることです。
Statement.setFetchSize(10)
を設定してみましたが、OS からまったく同じメモリが取得され、違いはありません。これには Microsoft SQL Server 2005 JDBC Driver を使用します。
Oracle データベース ドライバーのように、結果を小さなチャンクで読み取り、クエリの実行時に数行だけを表示し、下にスクロールするとさらに多くの結果を表示する方法はありますか?
JDBC では、
setFetchSize(int)
メソッドは、JVM からデータベースへのネットワーク呼び出しの数と対応するデータ量を制御するため、JVM 内のパフォーマンスとメモリ管理にとって非常に重要です。結果セットの処理に使用される RAM。基本的に、setFetchSize(10) が呼び出され、ドライバーがそれを無視する場合、可能なオプションは 2 つだけです。
RESULT-SET は、クエリに応答してデータベース上でマーシャリングされた行の数です。 ROW-SET は、JVM から DB への呼び出しごとに RESULT-SET から抽出された行のブロックです。 これらの呼び出しの数と処理に必要な RAM は、フェッチ サイズの設定によって異なります。
つまり、RESULT-SET に 100 行があり、フェッチサイズが 10 の場合、 すべてのデータを取得するために常に 10 回のネットワーク呼び出しがあり、約 10*{row-content-size} RAM が使用されます。
デフォルトのフェッチサイズは 10 ですが、これは非常に小さいです。 投稿されたケースでは、ドライバーはフェッチ サイズの設定を無視し、1 回の呼び出しですべてのデータを取得しているようです (大量の RAM が必要で、ネットワーク呼び出しは最小限が最適です)。
ResultSet.next()
で何が起こるかというと、実際には RESULT-SET から一度に 1 行ずつ取得するわけではありません。このデータは (ローカル) ROW-SET から取得され、ローカル クライアント上のデータが使い果たされると、サーバーから次の ROW-SET (非表示) を取得します。設定は単なる「ヒント」であるため、これはすべてドライバーに依存しますが、実際には、これが多くのドライバーとデータベースで機能することがわかりました (Oracle、DB2、および MySQL の多くのバージョンで実証されています)。 p>