Grails one-to-many选择id非常慢

时间:2014-12-24 05:03:22

标签: hibernate grails one-to-many

我在应用程序的某些部分遇到了一些非常慢的性能。 我们假设我有以下课程。

class Instrument{
 BigDecimal Value;
 String name;    
 InstrumentType type;
 InstrumentSubType sType;
 Country cls;
 Region reg;
 Sector sec;     
 static hasMany = [belongings: belongs] 
}

class DailyValuation{
   Instrument ins;
   Date valData;
   BigDecimal actualValue;
}

如果我想先插入一个新的DailyValuation,我需要获取该仪器。 因此,在测量时间后,我得到了:仪器选择仅需要一秒钟 500行,插入需要30毫秒。

如果我对Mysql进行常规查询,则选择时间不到10毫秒。我知道Hibernate有一些懒惰和急切的提取功能,所以:

有没有办法只选择我需要的东西?在我的情况下,我只需要仪器ID。 我尝试过以下方法:

def nin = Instrument.executeQuery("select a.id from Instrument a where name='BONUS1'")
DailyValuation dVal = new DailyValuation(ins:nin); 

在观看Hibernate Log SQL之后,我有一个选择哪个获取id,另一个选择获取整个乐器信息。

我应该如何进行以便尽可能快地获得此信息?

非常感谢你的帮助。

1 个答案:

答案 0 :(得分:1)

使用集合的默认GORM映射会很慢,而且随着集合大小的增加而更加如此​​。添加新DailyValuation的典型模式是使用基于该域类的addToBelongings映射中的键生成的动态hasMany方法。默认情况下,该集合是延迟加载的,因此如果它尚未初始化,则现在将完全填充,然后将添加新实例(如果映射是双向的,则将其引用到父集合),以及你保存父节点,Hibernate会注意到有一个新实例并保存它。但这是一种非常浪费的方法,无需加载所有500个实例。

从技术上讲,它不是没有 - 默认情况下集合是Set,因此Hibernate需要加载所有其他实例以确保新实例是唯一的。如果你将它配置为List,Hibernate需要所有其他实例以确保它处于正确的位置,即使你只是将它添加到最后。

更直接,更高效的方法是不使用集合,而只是在保存之前在子节点中设置父实例。从hasMany类中删除Instrument属性,当您创建新的DailyValuation实例时,只需自己设置Instrument,例如

Instrument parent = ...
def dailyValuation = new DailyValuation(params)
dailyValuation.ins = parent
if (dailyValuation.save()) {
   ...
}
else {
   ...
}

几年前我做了一个talk on this topic仍然相关。