【问题标题】:Optimisation: Eager fetching of base domain class instances优化:渴望获取基域类实例
【发布时间】:2014-09-17 09:10:04
【问题描述】:

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

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

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

对文档的访问由 ACL 控制,该 ACL 以另一个域类为模型。

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

ACL 已预先获取文档,并声明了批​​次以优化阅读文档。

class Document {
}

class Image extends Document {
}

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

}

启用 Eager fetching 并没有显着提高性能。

已启用 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 它不应该从表中获取子类的数据,因为它没有必要:只使用基类?

【问题讨论】:

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


    【解决方案1】:

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

    要解释为什么这是不可能的,您需要从 ORM 的角度来考虑这一点。在您的域示例中,您在此处显示“文档”没有被保存,“图像”是。具体实例始终是“图像”而不是“文档”。为了水合文档列表,ORM 不仅必须加载来自基类的数据,还必须加载实现类的数据。这是无法避免的。避免这种情况会创建一个不是域的有效表示的类的实例。

    这是使用 ORM 必须付出的代价之一。

    【讨论】:

      猜你喜欢
      • 2011-12-09
      • 1970-01-01
      • 2014-05-15
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      • 2012-11-12
      • 2015-03-10
      • 2023-03-09
      相关资源
      最近更新 更多