2008-12-23 73 views
0

我正在使用Java和Hibernate的JPA實現構建數據庫Web應用程序。應用程序跟蹤對象。它還需要從傳統源批量導入對象。批量導入大型數據集時的數據庫性能建議

例如,假設我們正在跟蹤的人。該數據庫具有名爲個人和地址的表。有相應的JPA實體和DAO類。

在JPA層的頂部是負責各種操作的服務層。一項操作是從外部遺留源(例如電話簿中的人員)導入潛在的大量數據。對於每個人,都必須檢查它是否已經存在於數據庫中。然後必須根據需要創建或更新該人員。每個人都有一個地址,因此必須進行適當的交叉引用和地址創建。

我的問題是,這種操作可以爲大型數據集緩慢。我目前的算法是:

for (Person person: allPersons) 
{ 
    check if person exists in database 
    check if address exists in database 
    create or update person and address as necessary 
} 

您會建議如何改善性能?

把我的頭,我能想到的頂部:

  1. 更改導入邏輯檢索和存儲數據使用的查詢數據庫。例如,不是檢查for循環中是否存在person,而是在一個查詢中將所有person key提交給數據庫,每個進程檢索內存中的person。
  2. 在DAO類中添加我自己的緩存。
  3. 使用外部緩存解決方案(如memcached)。

我能#1通過重組以減少查詢始終走。缺點是我的服務層現在非常瞭解DAO層。它的實現現在由較低的數據庫層決定。還有其他問題,如使用太多的內存。這種從數據庫中獲取內存然後在內存中進行處理似乎非常有用,並且不符合JPA等現成的解決方案。我很好奇別人在這種情況下會做什麼。

編輯:緩存將不利於爲每個人所內環路查詢是不同的。

回答

1

我找到了兩種解決方案。一個是一次處理一個塊。每個塊關閉後重新啓動會話。我曾嘗試在會話中使用清除清除方法,但有時候它的功能正如您所期望的那樣。開始和停止批次之間的交易似乎是最好的。

如果性能是一個主要關注點,那麼您只需要在JDBC中分解並執行它。 Hibernate增加了批量處理大量數據集的開銷,其中內存和性能非常重要。

+1

其中一個原因是沖洗不總是釋放內存的是,hibernate將存儲對事務中保存的所有對象的引用,以便它可以在事務結束時調用對象上的提交掛鉤(如果有的話)。 – davidsheldon 2009-01-04 10:04:52

0

你的做法是將導致對數據庫中太多的個人查詢;看起來像4n + 1。如果可能的話,我會寫一個查詢(可能是原始SQL),一次檢查是否存在person + address。

您可能想使用StatelessSession而不是標準的Hibernate Session。由於它沒有第一級緩存,因此應該保持較低的內存要求。

http://www.hibernate.org/hib_docs/reference/en/html/batch-statelesssession.html

如果不爲你工作,那麼你會想在休眠看看批處理選項:

http://www.hibernate.org/hib_docs/reference/en/html/batch.html