优化:急切获取基本域类实例

时间:2014-09-17 09:10:05

标签: hibernate grails gorm query-performance grails-2.3

Grails应用程序维护有关已保存文档的数据。

为具有名为Document的基本域类的域类创建了简单的域类层次结构。

目前使用table-per-subclass方法。它不是最有效的,但现在还可以。

使用ACL控制对文档的访问,ACL使用另一个域类建模。

在一种特殊情况下,无论实例类型如何(在顶层),都必须将分配给一个ACL的一堆文档分配给另一个ACL。

ACL急需提取文件,并声明批次以优化阅读文档。

class Document {
}

class Image extends Document {
}

class ACL {
  Collection documents
  static mapping = {
     documents   lazy: false, batchSize: 100
  }

}

启用急切提取并未大幅提升效果。

启用了SQL日志记录来分析问题。我发现Document的记录是按预期获取的,但是对于每个文档,当使用for循环进行迭代时,对文档集合中的每个元素执行附加的子类表连接查询。

ACL original = ACL.get(id)
for (doc in original.documents) {
  // Do whatever needs to be done
}

我认为触发了这种行为,因为doc没有使用显式类型。我试过这个:

ACL original = ACL.get(id)
for (Document doc : original.documents) {
  // Do whatever needs to be done
}

不幸的是它没有帮助。

有没有办法告诉Grails它不会从子类的表中获取数据,因为它没有必要:只使用基类?

1 个答案:

答案 0 :(得分:1)

不,没有办法告诉Hibernate(实际上这是做这个,而不是Grails)来做到这一点。如果需要这种类型的优化,则需要使用原始SQL,而不是HQL或基于GORM的查询。

要解释为什么这是不可能的,您需要从ORM角度考虑这一点。在您的域示例中,您已在此处展示了" Documents"没有被保存,"图像"是。具体实例总是" Image"永远不会"文件"。为了水化文档列表,ORM不仅必须加载来自基类的数据,还要加载实现类。这是不可避免的。避免这种情况会创建一个类的实例,该类不是域的有效表示。

这是您使用ORM必须支付的价格之一。