我在应用程序的某些部分遇到了一些非常慢的性能。 我们假设我有以下课程。
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,另一个选择获取整个乐器信息。
我应该如何进行以便尽可能快地获得此信息?
非常感谢你的帮助。
答案 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仍然相关。