2015-07-10 53 views
0

在我的Grails应用程序我正在使用的一些技术非常兴奋,但最近我遇到一些问题的表现,我会介绍我的cenario慢慢性能:Grails的AddTo就*与事件

用4M + entires
  • 一个表;
  • 我正在使用Event Bus API;
  • Grails 2.2.3;
  • MySQL DB;

当客户端创建新房间时,也会创建一些Alloc。

pseudo-code: 
    Room { 
     hasMany = aloccs: Alloc 
    } 

看这段代码(不是真正的代码,但同样平等):

@Listener(topic="topicAlocCreator") 
def alocCreator(EventMessage<Long> message) { 

    LocalDate start = new DateTime().toLocalDate() 
    LocalDate end = new DateTime().plusYears(2).plusMonths(6).toLocalDate() 
    LocalDate tmp = start 


    Room room = Room.get(message.data) 
    List channels = Channel.list 
    while(tmp.compareTo(end) <= 0) { 
     for(channel in channels) { 
      room.addToAlocs(new Aloc(0, 0, tmp.toDate(), channel)) 
     } 
     tmp = tmp.plusDays(1) 
    } 

    //end of method 
} 

此代码工作正常,但它产生了大量的alloc的对象,并把它放在一个Hibernate会话。

什么是使用flush来完成这项工作的正确方法?批量? - 调用方法是assync。

此代码工作正常,直到(07/14),但在这段时间内,它很慢,比如1.30分钟,在数据库中插入10K的alloc;

非常感谢您的建议。

回答

2

因为allocsSet(默认的Grails集合类型,当你定义一个hasMany关系),Grails的有整个集合加载到内存之前插入可以为了保证唯一性发生。

查看Bert Beckwith的presentation关于使用GORM集合的性能影响。

我想你有几个选择。你可以用完全收集参考免除了,只是这样定义你的类:

class Alloc { 
    Room room 
} 

class Room { 
    //no reference child Allocs 
} 

或者,你可以定义你allocs集合作为一个袋:

在这种情况下
class Alloc { 
    static belongsTo = [room: Room] 
} 

class Room { 
    Collection allocs 
    static hasMany = [allocs: Alloc] 
} 

有没有必要唯一性检查和addTo...方法将不需要将每个Alloc实例加载到内存中。但是您的话负责维护自己的独特性......

Reference

+0

我使用的是德清单,以及休眠创建我的数据库alloc_idx,使用收藏更performatic呢? –

+1

绝对不是更好(整个集合不必从数据库加载而不管集合类型),实际上可能更糟糕。使用Set只保证唯一性,因此Hibernate检测到Set中添加和删除的实例并进行相应的单个数据库更新。该附加列用于跟踪列表内的顺序,如果打开SQL日志记录,您将看到Hibernate将删除所有实例,并在订单更改时重新插入它们,而不是更新idx列。 –

+0

事实证明,使用掌上电脑不解决这个问题,可以让工作的事情 - 我写了在[本博客文章(http://burtbeckwith.com/blog/?p=1029) –