如何在Grails中实现批处理
How to implement batch processing in Grails
我有一个 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()
}
}
}
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
}
}
每 x 行的 GORM 清理使批处理作业线性扩展
这和原来的问题有很大的不同,所以如果我理解正确的话,你需要将不同的信息加载到通过不同的数据源访问的表中。您在项目中定义了多个数据源。
并且您想将 groovy.sql.Sql 与这些数据源一起使用。
您的所有数据源都可以通过 dataSource_dataSourceName 在您的 grails 应用程序上下文中使用,因此它就像注入数据源并以与您的第一个代码片段非常相似的方式创建 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
我有一个 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()
}
}
}
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
}
}
每 x 行的 GORM 清理使批处理作业线性扩展
这和原来的问题有很大的不同,所以如果我理解正确的话,你需要将不同的信息加载到通过不同的数据源访问的表中。您在项目中定义了多个数据源。 并且您想将 groovy.sql.Sql 与这些数据源一起使用。
您的所有数据源都可以通过 dataSource_dataSourceName 在您的 grails 应用程序上下文中使用,因此它就像注入数据源并以与您的第一个代码片段非常相似的方式创建 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