2014-01-16 89 views

回答

6

我們在生產中使用hibernate.default_batch_fetch_size = 100。所以在某些情況下,我們有3個查詢,而不是300個,所以這對我們的數據庫來說是一個很好的提升。

4

總結:

當批量抓取被打開,Hibernate準備很多的查詢:這些查詢需要大量的存儲器不能被garbaged。批量大小爲1000將需要150M的RAM。

所以,具有低一般批量大小(如10,20或40)是最好的,只用於與@BatchSize註釋特定集合設置更大的批量大小。

詳細信息:

正在獲取批量這裏Understanding @BatchSize in Hibernate解釋說,「了hibernate.default_batch_fetch_size」是一般參數和「@BatchSize」註解允許覆蓋在某個特定關聯的一般參數。

但是這些解釋並沒有真正回答「官方文檔爲什麼推薦值爲4,8或16」的問題?顯然,現代數據庫可以在IN子句中處理多於16個值的查詢,並且在IN子句中使用1000個值進行查詢將允許執行更少的查詢,從而可以獲得更好的性能......所以,爲什麼不設置1000作爲批量?

我這樣做了,我把1024作爲批處理大小,並且答案很快就出現了:tomcat服務器需要更多的時間才能啓動並且在調試日誌中我可以看到很多行「Static select for entity ...」 。

發生了什麼事是,Hibernate的準備數千靜態查詢,這裏是日誌的實體的一部分:

... 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?, ?, ?, ?, ?, ?, ?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?, ?, ?, ?, ?, ?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?, ?, ?, ?, ?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?, ?, ?, ?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?, ?, ?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?, ?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id in (?, ?) 
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock) where id = ? 
... 

正如你所看到的,Hibernate的準備批量抓取請求,但不是所有的請求。 Hibernate爲1,2,3 .... 10個參數準備所有請求,然後只准備一些參數等於batchSize /(2^n)的請求。例如,如果batchSize = 120 => 120,60,30,15,10,9,8,...,2,1

因此,我嘗試使用各種數量的元素對集合進行批量提取,和的結果是:

  • 有關讀取18個項目,休眠製成2個查詢:一個具有16個項目和一個與2項。

  • 對於獲取16個項目,hibernate用16個項目進行了1個查詢。

  • 對於獲取12個項目,hibernate提出了2個查詢:一個包含10個項目,另一個包含2個項目。

Hibernate只使用在啓動時準備的語句。

之後,我監視的所有這種準備的語句的RAM的使用:

  • 與BATCHSIZE = 0 => 94的Mo(它是我的參考)

  • BATCHSIZE = 32 => 156沫(62沫與基準)

  • BATCHSIZE = 64 => 164沫(68沫與基準)

  • BATCHSIZE = 100 0 => 250 Mo(+156!與基準莫)

(我的項目屬於中等規模,約300單位)

現在是時候爲結論

1)BATCHSIZE可以有很大的影響在啓動時和內存消耗。它不與批量大小成線性關係,80的批量大小將比10的批量大2倍。

2)Hibernate無法檢索具有任意大小的批次的項目集合,它只使用準備好的批量查詢。如果將batchSize設置爲120,則準備的查詢將爲具有120,60,30,15,10,9,8,7,6,5,4,3,2和1個參數的查詢。因此,如果您嘗試使用220個項目獲取收藏,則會發射4個查詢:第一個將檢索120個項目,第二個60,第三個30和第四個10.

這解釋了爲什麼建議的batchSizes較低。我會建議設置一個低的全局batchSize,比如20(20對我來說比16好,因爲它不會生成比16更多的準備好的查詢),並且只在需要時才設置特定的更大的@BatchSize。

(我使用休眠5.1)

1

關於內存/啓動時間的顧慮。 與嘗試:

<property name="hibernate.batch_fetch_style" value="dynamic" /> 

只有一個?「其中id =」,但在會議上同類型的實體的批量抓取動態與了hibernate.default_batch_fetch_size的極限構造準備好的聲明。