2010-03-19 55 views
0

當我嘗試獲取大約20,000條記錄並返回到ArrayList時,它會拋出java堆空間錯誤。當從數據庫提取記錄時發生java.lang.OutOfMemory錯誤

JdbcTemplate select = new JdbcTemplate(dataSource); 
      String SQL_SELECT_XML_IRP_ADDRESS = " SELECT * FROM "+ SCHEMA +".XML_ADDRESS "+ 
                " WHERE FILE_NAME = ? "; 
      Object[] parameters=new Object[] {xmlFileName}; 
      return (ArrayList<XmlAddressDto>) select.query(SQL_SELECT_XML_ADDRESS, 
        parameters,new XmAddressMapExt()); 

我們的數據庫是Oracle並使用oracle瘦驅動程序。
有沒有解決方案?我應該如何有效處理這個問題?

+0

你真的需要弄個20,000個嗎?你需要什麼?什麼是功能要求?最終答案也可能取決於所使用的DB和JDBC驅動程序。發佈有關它的細節。 – BalusC 2010-03-19 13:26:43

回答

3

的答案是很難不知道你的系統的細節,但有幾個選項:

  • 增加內存的JVM(見如此多的其他問題)
  • 避免在加工過程中的所有記錄在一旦;嘗試攫取您的查詢的一個子集,然後重複該過程,而不是立即嗅探所有內容
  • 嘗試減少您閱讀的數據量:您是否確實需要執行SELECT *
1

您是否需要一次保存所有20,000條記錄的所有字段?

大概你需要處理它們併產生一些數據。 然後建立你的算法,使它在讀取N個記錄時(比方說100),處理它們,然後移動到下一組。

您可能還想看看Spring的SqlQuery類,它可以幫助您對由SQL查詢返回的結果集執行計算。

1

你真的需要所有的20000結果保存在內存中嗎?

如果您只是想處理所有20000個結果,則應該使用RowCallbackHandler對每行進行處理,並使用setFetchSize()來避免完整的選擇內存。

+0

我想獲取那麼多的記錄並存儲到List對象中。 是否有可能使用RowCallbackHandler返回List? – 2010-03-26 11:53:50

+0

是的,但是你將不得不擁有20000個列表元素 - 沒有贏得 – 2010-03-26 15:29:32

1

這裏的核心問題是,您可能沒有足夠的內存在內存中存儲20,000個XmlAddressDto對象的副本。一對夫婦的選項有:

  1. 添加更多內存(或更大的堆,使用-Xmx啓動JVM時)
  2. 有一個子集工作在內存中 - 要麼懶洋洋地初始化集合(如高速緩存只有最後200 ,或者這樣的條目,通過數據庫打其他人)。你甚至可以將這個集合包裝在List接口中,這可能會完成你想要做的事情 - 儘管你必須小心訪問,或者像迭代它的成員那樣的事情
  3. Figure how to make the XML object更小 - 如果DTO是完整的樹對象,可能會存儲二進制或字符串表示形式,如果需要使用它,則將其解壓縮 - 尤其是如果您只是將完整的XML傳遞給其他代碼以便使用。