繁体   English   中英

Grails /休眠的渴望获取似乎被忽略了

[英]Grails/hibernate Eager Fetching appears to be ignored

我正在解决一些性能问题,这些性能问题似乎与对数据库的重复调用有关(数千个对象加载了数十个子对象)。

问题似乎是,尽管急切地加载了关系(并通过登录休眠SQL确认急切地加载了对象),但每次仍从数据库中获取它们。

我的直觉是问是否有一种方法可以让grails / hibernate在内存中使用该对象,而不是在肯定的情况下返回数据库呢?

但是,这可能是一个错误的问题。


举例说明正在发生的事情。 我的域类Parent定义:

static hasMany = [children: Child]
static mapping = {children fetch:'select'}

可能是获取:'eager'...我尝试了两种方式,不确定是哪个生成了下面的日志结果,但是显然是在急切地获取数据。

我要做的第一件事是:

def结果= Parent.executeQuery(“从父p WHERE ...复杂where子句中选择不同的p”)

查看日志,这不会急于加载子关系,但这并不是非常意外的,并且在这一点上还不是真正的杀手er。 接下来,我遍历父母:

for(Parent parent : results)
{  blah blah }

循环的每次迭代都表明,hibernate正在通过id查询Parent p,并且似乎渴望加载所有子关系。 日志片段:

select 
parent0_.id as id4_4_, 
parent0_.version as version4_4_, 
parent0_.date_created as date3_4_4_,
child1_.parent_id as parent6_6_, 
child1_.id as id6_, 
child1_.child_idx as idx9_6_, 
child1_.id as id22_1_, 
child1_.version as version22_1_,
...continues for all fields.

注意:我不知道为什么它两次映射id字段。

大! 它急切地加载,我需要的子对象! 在上面的父循环中,然后遍历子节点:

for(Parent parent : results)
{  
  for(Child child : parent.children)
  { blah blah }
}

这就是问题所在。 内循环的每次迭代,都会记录另一个休眠查询,并按ID加载对象。 日志片段:

select child0_.id as id22_1_, 
child0_.version as version22_1_, 
child0_.parent_id as parent6_22_1_, 
child0_.sequence_number as sequence8_22_1_,
...and all the rest

这些不必要的负载绝对会破坏我的性能(至少,这似乎是瓶颈,我不能百分百确定),因为它正在执行数千次读取。 非常感谢您对如何在内存对象中正确使用或以其他方式加载数据的任何想法。

我发现,在mapping中设置fetch不足以使grails使用热切的fetching。 尽管gorm手册中未提及,但似乎还有另一个属性fetchMode 尝试将其添加到您的域类中:

static fetchMode = [children: 'eager']

对于意识到我一定做错了事情的人来说,这并不奇怪。 该对象已被缓存,但是在子例程中有一个parent.refresh()被调用。 似乎刷新正在执行多个查询来加载子对象,一旦删除刷新,我将不再看到额外的查询,但是似乎刷新应该执行与初始加载相同的单一查询,而不是对子对象。 我的代码中可能有其他我未完全调试的错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM