2015-02-23 141 views
0

這個函數是我寫的一個Hibernate程序,用於爲大學金融系統做一些後端批量處理。程序執行時會被調用數十萬次,這些調用是程序中最大的單次調用。目前我想不出一種合理的方式來減少它的使用次數。這種Hibernate方法效率很低嗎?

此函數以財政年度支付期(「fypper」)和該期間的一週爲參數,並返回一個構造(「AidYearTerm」),該構造存儲支付週期所在的年份,學期和期限英寸

public AidYearTerm FypperTermInfo (String fypper, String week) { 

    sfa_fws_calendar aidYear = new sfa_fws_calendar();  

    TypedQuery<sfa_fws_calendar> query = manager.createQuery("FROM sfa_fws_calendar cal " 
      + "WHERE cal.id.fypper = ?1 AND cal.id.week_num = ?2",sfa_fws_calendar.class); 
    query.setParameter(1, fypper); 
    query.setParameter(2, week); 

    List<sfa_fws_calendar> aidYearList = query.getResultList(); 

    if(!aidYearList.isEmpty()) { 
     aidYear = query.getSingleResult(); 
    } 
    else { 
     aidYear.setFWS_AID_YR("9999"); 
     aidYear.setSEM("NOTSET"); 
     aidYear.setTERM("NOTSET"); 
     ErrorOut("Could not find term info for "+fypper); 
    } 
    DebugOut("found aid year "+aidYear.getFWS_AID_YR()+", term "+aidYear.getTERM()); 

    AidYearTerm aidYearTerm = new AidYearTerm(aidYear.getFWS_AID_YR(),aidYear.getTERM(),aidYear.getSEM()); 
    return aidYearTerm; 

} 

有什麼我可以做,使這更簡單/更快?

+0

「被調用幾十萬次」 - 數據庫查詢,執行數十萬次?如果除了極大地減少這個數字之外沒有太多的改進,我們不會感到驚訝。 – JimmyB 2015-02-23 16:16:40

+0

順便說一下,數據庫中有多少年和幾周的組合? - 如果它不是數百萬,我認爲它不是,它應該很容易讀取一次,例如存儲在一個'HashMap'中,然後操作這個緩存的數據。 – JimmyB 2015-02-23 16:21:32

+0

約有11,000種組合。在將它們存儲在散列表中並參考它而不是重新查詢之後,過去需要兩個小時的過程現在大約需要十五分鐘。謝謝! – 2015-02-23 18:42:06

回答

0

乍一看:

List<sfa_fws_calendar> aidYearList = query.getResultList(); 

if(!aidYearList.isEmpty()) { 
    aidYear = query.getSingleResult(); // <========= DON'T!!!!! 
} 

Query.getSingleResult()再次運行相同的查詢!

用途:

List<sfa_fws_calendar> aidYearList = query.getResultList(); 

if(!aidYearList.isEmpty()) { 
    aidYear = aidYearList.get(0); 
} 

編輯:

假設你沒有數以百萬計的年份和周鍵記錄,似乎可行的讀取sfa_fws_calendar所需的所有數據到內存中只有一次,例如轉換爲Map,以便隨後避免數千次往返數據庫。

需要注意的是,因爲fypperweek實際上形成(串)組合鍵,你可以建立一個Map<String, AidYearTerm>,其中的鍵可以,例如,year + "_" + week。然後你的FypperTermInfo (String fypper, String week)只會return aidYearCacheMap.get(fypper + "_" + week);和voilà:)

0

最簡單和最明顯的優化將是這樣的:

static final TypedQuery<sfa_fws_calendar> query = manager.createQuery("FROM sfa_fws_calendar cal " 
     + "WHERE cal.id.fypper = ?1 AND cal.id.week_num = ?2", sfa_fws_calendar.class); 

public AidYearTerm FypperTermInfo(String fypper, String week) { 

    //... 
    query.setParameter(1, fypper); 
    query.setParameter(2, week); 

    List<sfa_fws_calendar> aidYearList = query.getResultList(); 

不知道叫createQuery的開銷,但是這肯定只能得到一次發生。然後,如果所有東西仍然在爬行(這很可能),那麼可以考慮某種形式的緩存(可能爲ehcache),但只有在組合數量相對較少的情況下才有效。

0

這看起來像一個非常簡單的選擇,所以我認爲這可能是更多的問題圍繞確保Oracle有效地運行它(特別是因爲它每天運行數千次)。你對這個查詢看到了什麼樣的解釋計劃?有沒有全表掃描?您可能需要對sfa_fws_calendar表進行索引,或者如果已經存在索引,請更改適當的索引並重新計算索引統計信息。

例如,這樣的事情可能會幫助更新現有的索引稱爲INDEX_NAME:

ALTER INDEX index_name REBUILD COMPUTE STATISTICS;