如何在使用Grails hasMany关系时解决潜在的性能问题?

时间:2008-11-14 02:41:27

标签: performance hibernate grails groovy

给出以下域类:

class Post {
   SortedSet tags
   static hasMany = [tags: Tag]
}

class Tag {
   static belongsTo = Post
   static hasMany = [posts: Post]
}

根据我的理解,使用hasMany将导致hibernate Set映射。 但是,为了保持唯一性/顺序,Hibernate需要从数据库加载整个集合并比较它们的哈希值。

这可能会导致添加和删除帖子/标签时出现严重的性能问题 如果他们的集合变大解决这个问题的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

默认映射中Hibernate / GORM没有确保顺序。因此,它不必从数据库加载元素以进行排序。你将掌握一堆id,但这就是它的范围。

见19.5.2: http://www.hibernate.org/hib_docs/reference/en/html/performance-collections.html

通常,Hibernate / GORM的性能会比您预期的要好。除非并且直到您能够真正证明现实世界的性能问题,否则请相信框架并且不要担心它。

答案 1 :(得分:0)

Set实现保证了集合的顺序,即SortedSet。除非您使用跟踪数据库索引的List,否则排序只是服务器端。

如果您的域类位于SortedSet,则必须实施Comparable才能正确对该集合进行排序。

性能问题本身并不是一个问题。如果您想访问单个Tag,则应通过 ID 获取。如果你想要排序的标签,那么排序只有在你查看所有Tags而不是特定标签时才有意义,所以你最终一次检索所有Tags。由于排序是在服务器端执行而不是在数据库端执行,因此关于Db,SortedSet和常规HashSet之间没有太大区别。

答案 2 :(得分:0)

Grails文档似乎已更新:

http://grails.org/doc/1.0.x/

在5.2.4节中,他们讨论了集合类型的潜在性能问题。

以下是相关部分:

关于收集类型和效果的说明

Java Set类型是一个不允许重复的集合。为了确保在向Set关联添加条目时的唯一性,Hibernate必须从数据库加载整个关联。如果关联中有大量条目,则在性能方面可能会很昂贵。

List类型需要相同的行为,因为Hibernate需要按顺序加载整个关联以维护顺序。因此,如果您预期关联中存在大量记录,则建议您将关联设置为双向,以便可以在反面创建链接。例如,请考虑以下代码:

def book = new Book(title:"New Grails Book")
def author = Author.get(1)
book.author = author
book.save()

在此示例中,关联链接由子(Book)创建,因此不必直接操作集合,从而减少查询和更高效的代码。如果您编写了如下代码,那么如果您的代码具有大量关联的Book实例,那么您会看到对性能的影响:

def book = new Book(title:"New Grails Book")
def author = Author.get(1)
author.addToBooks(book)
author.save()