2011-06-17 63 views
0

對於Grails上的大插入批次,我有很多麻煩。我嘗試了用戶提出的所有最常見的解決方法(比如WithTransaction等),並且插入仍然很慢。大批量插入:如何從Grails獲取INSERT SQL代碼?

我有一批約500K的對象。在Gorm上,DB中的對象創建/插入每插入約200毫秒,這顯然是不可接受的。 如果我從轉儲文件中的應用程序生成相關的SQL INSERT語句,然後直接在DBMS上運行轉儲文件,則每插入1毫秒會得到<,這更像它。 爲了使該批次線上,我想這個解決方案(僞Groovy代碼)的:

FileBuffer sqlFile = ... 
largeBatch.each{ 
    def obj = createMyObject(it) 
    String sql = getSQL code for obj insert 
    sqlFile.write(sql) 
} 
execute sqlFile directly on JDBC 

我怎樣才能得到一個短暫的對象插入SQL代碼?

回答

0

有2種方式,用於插入的數據執行快速批量處理:

  1. 冬眠無狀態會話(http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch .html)
  2. native sql(http://groovy.codehaus.org/api/groovy/sql/Sql.html)(創建x插入語句並在x數據庫事務中激發它們)例如您可以創建一個單一的SQL轉儲並在單個事務中激發該轉儲。

與休眠無狀態會話,您還可以批量插入,並可以插入域類實例,例如session.save(OBJ)。與navite SQL你必須建立你自己的聲明。

+0

感謝。是否可以提取Hibernate在GORM中生成的SQL代碼? – Mulone

0

Ted Naleidgood write-up提高了批量插入/更新性能。你遇到過嗎?他的建議已經爲我批量更新。

下面是摘錄下來更低的文章:

通常情況下,一個Grails Hibernate會話 快速 回報執行的東西。在導入過程中,我們執行了一個處理過程,所有的hibernate會話都使用相同的 。所有這些 對象通常會在垃圾 收集時關閉會議 堆積。

處理此問題的最簡單方法是使用 創建一個簡單的方法,以定期清除這些收藏夾 。

他建議定期刷新並清除會話。

data.eachWithIndex { datum, index -> 
    // insert or update datum 
    if(index % 100 == 0) { 
     def session = sessionFactory.currentSession() 
     session.flush() 
     session.clear() 
     // also clear the Grails domain class property instance map 
     // - it may be that this isn't necessary anymore; not sure, but the article is 
     // a bit old, so maybe it's been fixed within Grails. 
    } 
} 

利用這一點,他提高了從100K記錄批量插入約2.5小時至3分鐘。

@Ted - 如果你遇到這個問題/答案,並且想自己重複這個答案,我會非常樂意刪除我的答案並且讚揚你的;你完成了所有的努力工作。謝謝!

+0

我試過這個解決方案,我也有內存泄漏。我在這個階段厭惡GORM,所以我認爲在這種情況下,我將生成SQL並在dbms上離線運行它。我只是想知道是否有一個聰明的發現來獲得從休眠生成的SQL。 – Mulone

0

您可以使用自定義Hibernate配置子類來捕獲啓動時生成的SQL。我不確定稍後訪問它的最佳方式是什麼 - 可能是該課程中的一個公共靜態字段。

下面的代碼(把它在src/JAVA):

package com.yourcompany.yourapp; 

import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration; 
import org.hibernate.HibernateException; 

public class DdlCapturingConfiguration extends GrailsAnnotationConfiguration { 

    @Override 
    public String[] generateSchemaCreationScript(Dialect d) throws HibernateException { 
     String[] sql = super.generateSchemaCreationScript(d); 
     // do something with the sql 
     return sql; 
    } 
} 

,你會在grails-app/conf/DataSource.groovy這樣註冊它:

dataSource { 
    pooled = true 
    driverClassName = ... 
    username = ... 
    password = ... 
    dialect = ... 
    configClass = com.yourcompany.yourapp.DdlCapturingConfiguration 
}