【问题标题】:How to implement batch processing in Grails如何在 Grails 中实现批处理
【发布时间】:2015-05-14 11:02:33
【问题描述】:

我有一个 Grails 应用程序,它实现了多个数据源及其任务来处理和保存相应数据源表中的 excel 数据(xlsx 类型)。但是当excel文件包含大量数据并且需要更多时间来保存时,我遇到了问题。所以我使用 SQL 并通过批处理插入值,它工作正常,保存值的时间最短,但它将值保存到常见的数据源表中。所以我又遇到了一个问题,我们如何在多个数据源中使用。

这工作正常,但我们如何在多个数据源中使用。我正在描述我们的查询 -

def dataSource      
def sql = new Sql(dataSource)        
sql.withBatch { stmt ->
    stmt.addBatch("INSERT INTO TableName(Fields...) values(.......)
    stmt.executeBatch() 
}

我不想通过列表来实现它,因为它需要大约相同的时间来保存,即

def dataSourceName = 'lookup'     
List list= []
(0..10000).each{
    Domain dom = new Domain('some property associated with domain class')
    batch.add(dom)
    if(list.size()>1000){ 
        for(Domain object in list){
            object."$dataSourceName".save()
        }
    }
}

【问题讨论】:

  • 你应该使用像 Spring Batch 这样的批处理框架。它与 Grails 和 Groovy 结合使用效果很好。

标签: grails grails-orm batch-processing


【解决方案1】:

Ted Naleid 有一篇文章描述了他在 GORM 中显着提高 Batch 性能的历程。这是一篇旧文章,但可能值得一试,看到令人印象深刻的性能提升。

http://naleid.com/blog/2009/10/01/batch-import-performance-with-grails-and-mysql

基本上是什么改变了 grails 中的一切,是在您的服务中添加以下内容:(来自 Ted Naleid 的文章,因为您的问题根本不清楚您要做什么,您只说您不想做的事情)

class BookService {
    def sessionFactory
    def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP

    def importBooksInLibrary(library) {
        library.eachWithIndex { Map bookValueMap, index ->
            updateOrInsertBook(bookValueMap)
            if (index % 100 == 0) cleanUpGorm()
        }
    }    

    def cleanUpGorm() {
        def session = sessionFactory.currentSession
        session.flush()
        session.clear()
        propertyInstanceMap.get().clear()
    }

    def updateOrInsertBook(Map bookValueMap) {
        // ... same as above
    }
}

GORM 清理每 x 行使批处理作业线性扩展

【讨论】:

【解决方案2】:

这与原来的问题有很大不同,所以如果我理解正确的话,你需要将不同的信息加载到通过不同数据源访问的表中。您的项目中定义了多个数据源。 并且您想将 groovy.sql.Sql 与这些数据源一起使用。

您的所有数据源都可以通过 dataSource_dataSourceName 在您的 grails 应用程序上下文中使用,因此就像注入数据源并以与您的第一个代码 sn-p 非常相似的方式创建 Sql 对象一样简单:

def dataSource_lookup
def dataSource_otherName

static transactional=false

def doWork() {
  def sql=new Sql(dataSource_lookup)
}

请注意,为了能够对不同的数据源进行事务处理,您需要将 XA 事务处理到位。

http://grails.github.io/grails-doc/2.2.1/guide/conf.html#multipleDatasources

【讨论】:

  • 我在服务中编写了我的代码,当我检查时,它看起来不像事务性的。我们如何使它成为事务性 = true。我也检查了“静态事务性 = true”,但它没有。
  • 您不能没有 XA 事务管理器。您正在与 2 个不同的数据库交谈。
  • 但一次我只使用一个连接,即一次将值保存到数据库的多个表中。所以这也是使用XA事务管理器的一个案例。请确认。
  • 如果您使用 2 个数据源,您将使用不同的连接池
猜你喜欢
  • 1970-01-01
  • 2010-11-20
  • 1970-01-01
  • 1970-01-01
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 2011-03-26
  • 1970-01-01
相关资源
最近更新 更多