2010-04-22 84 views
7

我有5個MySQL InnoDB表:Test,InputInvoice,InputLine,OutputInvoice,OutputLine,每個表都在Hibernate中映射和運行。我玩過使用StatelessSession/Session和JDBC批處理大小。我已經刪除了任何生成器類來讓MySQL處理這個id代 - 但它仍然表現得很慢。 這些表中的每一個表都在java類中表示,並相應地映射到休眠狀態。目前,當需要寫入數據時,如果我使用StatelessSession,則循環遍歷對象並執行session.save(Object)session.insert(Object)。當我的行數達到max jdbc批處理大小(50)時,我也會執行刷新和清除(當使用Session時)。休眠關係映射/加速批量插入

  1. 如果我在一個擁有這些對象的「父」類中做了這些,而不是每個都做了session.save(master)會更快嗎?
  2. 如果我把它們放在主/容器類中,我將如何映射hibernate以反映關係?容器類實際上不是它自己的表,而是一個基於兩個索引run_id(int)和line(int)的關係。
  3. 另一個方向是:我如何讓Hibernate做一個多行插入?
+0

我忘了提,每個這些表中有很多列 – ashurexm 2010-04-23 00:28:48

回答

7

對我來說,最終的解決方案是使用voetsjoeba的迴應作爲跳板點。 我的休眠配置使用以下選項:

hibernate.order_inserts = true 
hibernate.order_updates = true 
  • 我使用Session改爲 StatelessSession

  • 重新排序的 Java代碼來處理批量表中的所有元素 一次。所以表x的全部 ,表y等

  • 從各個 類中刪除了<generator>類。現在,Java創建並 其分配給對象

  • ,讓我確定是否只是 的ID被設定,而不是寫 「空」行到數據庫

  • 終於創造邏輯,我打開dynamic-insert 我的班,他們的休眠像這樣 定義:<class name="com.my.class" table="MY_TABLE" dynamic-insert="true">

14

ID生成策略對於在Hibernate中批量插入至關重要。特別是,IDENTITY代將通常而不是工作(注意AUTO通常映射到IDENTITY)。這是因爲在批處理插入過程中,Hibernate有一個名爲「requiresImmediateIdAccess」的標誌,表示是否立即生成生成的ID;如果是這樣,批處理被禁用。

當它說「立即執行標識插入」時,您可以很容易地在DEBUG級日誌中發現它 - 這意味着它已經跳過了批處理,因爲它被告知生成的ID在插入後立即需要。

典型的生成策略工作是TABLE和SEQUENCE,因爲Hibernate可以預先生成ID,從而允許批量插入。

快速確定批量插入是否工作的方法是激活DEBUG級日誌,因爲BatchingBatcher會明確告訴您正在執行的批量大小(「執行批量大小:」+批量大小)。

此外,以下屬性對於實現批量插入很重要。我不敢說,他們需要的是我不夠一個Hibernate-專家這樣做 - 也許這只是我的特殊配置 - 但在我的經驗,他們仍然需要:

hibernate.order_inserts = true 
hibernate.order_updates = true 

這些屬性相當差的記錄,但我相信他們所做的是使SQL INSERT和UPDATE語句正確分組以便批量執行;我認爲這可能是你之後的多行插入。如果我錯了,不要拍我,我從記憶中回憶起來。

我還會繼續並假設您設置了以下屬性;如果不是,這應該作爲提醒:

hibernate.jdbc.batch_size = xx 

其中xx是您希望的批量大小,當然。

+0

@JDR:非常感謝所有這些信息 - 我正在將我的ID生成更改爲本機(這是否會禁用批處理?),並會添加您的其他想法。我已經有jdbc.batch_size = 50,但沒有order_inserts/updates。我會讓你知道它的工作效果。 – ashurexm 2010-04-22 21:50:41

+0

@JDR:我實現了你的建議,我可以看到它將我的插入組合在一起,所以所有的表都按順序插入。它插入所有的測試,然後是所有的等.. 它顯示我的批量大小是50-這是很好的。 但是我仍然獲得了與之前大致相同的性能 - 這對於3300條記錄約爲5分鐘(請記住,每條記錄意味着一個插入到5個不同的表中)。 – ashurexm 2010-04-22 23:18:05

+1

@manyxcxi:由於requireImmediateIdAccess變量(使用H2和Hibernate 3.5.1-Final),將ID更改爲原生殘疾人批處理。如果配料商說它正在執行50個批次,那麼這就是它正在做的事情,這是這裏的目標。 5分鐘3300條記錄似乎有點過分,我可以在大約一秒鐘內插入1000條記錄,甚至有一些附加的Hibernate搜索開銷(儘管在嵌入式H2數據庫中)。我可以在任何地方看到一些示例輸出日誌嗎?你正在運行什麼數據庫以及你使用了哪個連接池? – voetsjoeba 2010-04-22 23:22:26