2010-02-20 107 views
5

我在Hibernate上執行批量插入MySQL時遇到了問題。Hibernate/MySQL批量插入問題

我使用Hibernate 3.3和MySQL 5.1

在較高的水平,這是發生了什麼事:

@Transactional 
public Set<Long> doUpdate(Project project, IRepository externalSource) { 
    List<IEntity> entities = externalSource.loadEntites(); 
    buildEntities(entities, project); 
    persistEntities(project); 
} 
public void persistEntities(Project project) { 
    projectDAO.update(project); 
} 

這導致在正日誌項(1爲每個行)如下:

休眠:(??????,,,,,)插入ProjectEntity(姓名,PARENT_ID, 路徑,PROJECT_ID,狀態,類型)值

我希望看到這個批處理,所以更新更高性能。這個例程可能會導致成千上萬行生成,並且每行的db行程是一個殺手。

爲什麼這不會成批? (這是我的理解,批處理插入應該在默認情況下通過休眠)。

回答

5

正如Chapter 13. Batch processing記載:

如果你正在從事批量 處理,你將需要啓用 使用JDBC批處理的。如果您想要 達到最佳性能,這是絕對必要的 。所述 JDBC批量大小設置爲合理數量 (10-50,例如):

hibernate.jdbc.batch_size 20 

休眠在 透明的關閉插入配料JDBC級別如果 使用身份標識發生器。

不要會話經常忘記flush然後clear否則你會得到OutOfMemoryException13.1. Batch inserts記錄。

但IMO,對於數萬行,你應該考慮使用the StatelessSession interface

+0

這會啓用SQL語句的批處理嗎? (會話是否保持狀態的聲音與批次正交,但也許我從類名推斷太多) – meriton 2010-02-20 20:06:28

+0

@meriton我已更新我的答案以添加更多詳細信息。 – 2010-02-20 20:29:09

+0

+1:現在我明白了,謝謝! – meriton 2010-02-21 16:08:40

0

Pascal在hibernate上下文中已經有很多東西了。作爲替代,您可以使用jbdc模板的Batchsqlupdate。不過,我必須警告你,hibernate緩存實例可能不會反映上面所做的更改。在我們的項目中,我們必須採取預防措施來克服這一點,創建一個不同的時間表(另一個問題,但在我們的控制範圍內)

7

帕斯卡的回答是正確的。但是,因爲您正在使用MySQL,所以我強烈建議您嘗試在JDBC URL中使用rewriteBatchedStatements=true參數。

此參數將導致JDBC驅動程序來動態地重新編寫插入批次使用一個單一的「多值」 INSERT,例如:

INSERT INTO mytable (mycol) VALUES (0); 
INSERT INTO mytable (mycol) VALUES (1); 
INSERT INTO mytable (mycol) VALUES (2); 

將被重新寫入:

INSERT INTO mytable (mycol) VALUES (0), VALUES (1), VALUES (2); 

這可以使在某些情況下顯著差異。有關示例測量,請參見http://www.jroller.com/mmatthews/entry/speeding_up_batch_inserts_for