私のクエリは、各行に 12 列の 31,000 の結果を返し、各行には約 8,000 文字 (行あたり 8KB) が含まれます。これが私が処理した方法です:
public List<MyTableObj> getRecords(Connection con) {
List<MyTableObj> list = new ArrayList<MyTableObj>();
String sql = "my query...";
ResultSet rs = null;
Statement st = null;
con.setAutoCommit(false);
st = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
st.setFetchSize(50);
rs = st.executeQuery(sql);
try {
System.out.println("Before MemoryFreeSize = " + (double)Runtime.getRuntime().freeMemory() / 1024 / 1024 + " MB");
while ( rs.next() ) {
MyTableObjitem item = new MyTableObj();
item.setColumn1( rs.getString("column1") );
... ...
item.setColumn12( rs.getString("column12") );
list.add( item );
} // end loop
// try to release some memory, but it's not working at all
if ( st != null ) st.close();
if ( rs != null ) rs.close();
st = null; rs = null;
}
catch ( Exception e ) { //do something }
System.out.println("After MemoryFreeSize = " + (double)Runtime.getRuntime().freeMemory() / 1024 / 1024 + " MB");
return list;
} // end getRecords
各行が 8kb のメモリを必要とする場合、31k は 242mb のメモリを必要とします。クエリ結果のループが終了した後、残りのメモリは 142 MB しかなく、他のプロセスの残りを完了するのに十分ではありません。
多くの解決策を検索し、ヒープ メモリを 512mb に設定しようとしました。-Xmx512m -Xms512m
また、フェッチ サイズも設定しましたsetFetchSize(50)
。
ResultSet がメモリを占有しすぎていると思われます。結果はクライアント側のキャッチに格納される可能性があります。ただし、いくつかのオブジェクト (st.close()
およびrs.close()
) をクリアした後、手動でガベージ コレクターを呼び出してもSystem.gc()
、ループ後の空きメモリは増加しません (なぜですか?)。
データベースの設計を変更することはできず、すべてのクエリ結果が必要であると仮定しましょう。処理後にメモリを解放するにはどうすればよいですか?
PS: また、 を使用せずResultSet.getString()
にハードコード文字列に置き換えようとしましたが、ループした後、450MB の空きメモリが得られました。
私がそうするなら、私はそれを見つけました:
// + counter to make the value different for each row, for testing purpose
item.setColumn1( "Constant String from Column1" + counter );
... ...
item.setColumn12( "Constant String from Column12" + counter );
counter++;
約60MBのメモリしか使用しませんでした。しかし、もしそうなら:
item.setColumn1( rs.getString("column1") );
... ...
item.setColumn12( rs.getString("column12") );
最大380MBのメモリを使用しました。
私はすでにrs.close();
とrs = null;
//rs is Result instance
を実行しましたが、これは役に立たないようです。これら 2 つのアプローチでメモリ使用量が大きく異なるのはなぜですか? どちらのアプローチでも、String のみを渡しました。