2016-09-19 57 views
0

我該如何處理內存不足5000萬記錄nhibernate,我在nhibernate中使用了無狀態會話並解決了大約170萬條記錄,但對我的報告不利。 另一件事是我需要計算他們,所以我不能分開的結果。 你能讓我知道如何優化它嗎?內存超過5000萬記錄c#nhibernate

 public IEnumerable<ATMDispenseReport> GetReport(string WhereClause) 
    { 

     var CurrentUnitOfWork = this.UnitOfWork as MainUnitOfWork; 

     var session = CurrentUnitOfWork.StatelessSession; 

     string SqlQuery = "MyQuery"; 

     var lstATMDispenseReport =session.CreateSQLQuery(SqlQuery)  .SetResultTransformer(Transformers.AliasToBean<ATMDispenseReport>()) 
      .List<ATMDispenseReport>(); 

     return lstATMDispenseReport; 
    } 
+0

你能舉一個例子說明你的數據是怎麼樣的以及你想要計算什麼?也許有一種方法可以在數據庫站點上進行計算,由sql查詢中的適當聚合啓動。 – Patrick

+0

ORM中的「O」代表Object。對象有bevahour。報告沒有對象,因爲它們沒有任何行爲。即使您堅持使用ORM進行報告,您也無法創建具有1.7M行的報告 - 沒有人類(或機器)能夠使用它。你想做什麼?在RAM中加載1.7M行不會使報告的速度超過只返回最終報告數據的SQL語句 –

+0

50M記錄是一個非常非常強的指標,您需要適當的報告模式和適當的ETL過程才能填充它。 –

回答

0

我假設你在x86(32位)上運行。 .NET中的一個數組(或一個List<T>)必須存儲在一個連續的內存塊中,因此,一個50萬個項目的列表將需要一個大於200MB的單個塊來存儲每個實例ATMDispenseReport(以及此會發生在幾個實例之後,因爲列表動態增長)。

儘管32位應用程序具有2GB內存限制,但如果您已經有一堆內容並且內存碎片化,則可能沒有足夠大的連續區域。然後你也有5000萬的對象,不需要連續分配,但它們可能至少比4字節指針大10倍。

  1. 骯髒的黑客?切換到64位,並檢查你的機器是否有足夠的內存。您也可能需要<gcAllowVeryLargeObjects>。請注意,對於平均大小爲40B的對象,您需要超過2GB的RAM。這對於單個查詢來說似乎有點奇怪,因爲我懷疑你的用戶真的需要一次全部這些行。

  2. 簡單的解決方案?用Enumerable<T>()替換List<T>()並枚舉結果,如果你真的需要枚舉全部的結果。這會延遲數據流,因此您只需要隨時在內存中保留一個元素。但請記住,所有這些數據仍需通過應用程序用於連接到DBMS服務器的套接字來傳遞。我們可能在談論幾個GB的數據。

  3. 更好的解決方案?重寫您的SQL,以便在SQL端彙總所有數據,然後再回到您的應用程序。讓DBMS服務器完成所有工作。

+0

非常感謝Groo我在本文之前嘗試瞭解決方案1,但它不工作,但我認爲解決方案2解決了我的問題。 –

相關問題