2008-11-14 5 views
1

Compte tenu des classes de domaine suivants:Comment contourner un problème de performance potentiel lors de l'utilisation d'une relation Grails hasMany?

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

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

De ma compréhension à ce jour, en utilisant un hasMany se traduira par la cartographie mise en veille prolongée SET. Cependant, afin de maintenir l'unicité/l'ordre, Hibernate doit charger l'ensemble complet de la base de données et comparer leurs hachages.

Cela peut entraîner un problème de performances important lors de l'ajout et de la suppression de messages/tags si leurs ensembles sont volumineux. Quelle est la meilleure façon de contourner ce problème?

Merci!

Répondre

1

Il n'y a pas d'ordre assuré par Hibernate/GORM dans le mappage par défaut. Par conséquent, il n'est pas nécessaire de charger des éléments de la base de données pour effectuer le tri. Vous aurez vos mains sur un tas de cartes d'identité, mais c'est tout.

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

En général, Hibernate/GORM va avoir de meilleures performances que vous attendez. À moins que vous ne puissiez réellement prouver un problème de performances dans le monde réel, faites confiance au framework et ne vous en faites pas.

+0

Merci pour le lien. Je suis d'accord que je devrais éviter une optimisation prématurée à ce stade. – Walter

0

La commande de l'ensemble est garantie par l'implémentation Set, soit le SortedSet. Sauf si vous utilisez un List, qui conserve une trace des index sur la base de données, la commande est uniquement côté serveur.

Si votre classe de domaine est dans un SortedSet, vous devez implémenter Comparable afin de permettre le tri correct de l'ensemble.

La question de la performance n'est pas vraiment une question en soi. Si vous voulez accéder à un seul Tag, vous devriez l'obtenir par son Id. Si vous voulez les étiquettes triées, eh bien, le tri n'a de sens que si vous regardez tous Tags, pas un particulier, de sorte que vous finissez par récupérer tous les Tags à la fois. Puisque le tri est effectué côté serveur et non côté db, il n'y a vraiment pas beaucoup de différence entre un SortedSet et un HashSet régulier en ce qui concerne Db.

+0

Avez-vous des documents/preuve que le tri est effectué côté serveur pour une SortedSet? –

+0

@Miguel, merci pour l'info je vais creuser plus profondément dans ce numéro. – Walter

+0

Les éléments de 'SortedSet' n'ont pas besoin d'implémenter' Comparable' tant que la collection est initialisée avec une implémentation de 'Comparator' (que vous pouvez attribuer à Hibernate en tant qu'attribut). – Yuval

0

Les Grails docs semble être mis à jour:

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

Dans la section 5.2.4, ils discutent les problèmes potentiels de performance pour les types de collections.

est ici la section pertinente:

Note sur les types de collecte et de performance

Le type Java Set est une collection qui ne permet pas de doublons. Afin de garantir l'unicité lors de l'ajout d'une entrée à une association Set, Hibernate doit charger toutes les associations à partir de la base de données. Si vous avez un grand nombre d'entrées dans l'association, cela peut être coûteux en termes de performance.

Le même comportement est requis pour les types Liste, car Hibernate doit charger l'ensemble de l'association afin de maintenir l'ordre.Par conséquent, il est recommandé, si vous anticipez un grand nombre d'enregistrements dans l'association, de rendre l'association bidirectionnelle afin que le lien puisse être créé du côté inverse. Par exemple, considérons le code suivant:

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

Dans cet exemple, le lien d'association est créée par l'enfant (Livre) et il est donc pas nécessaire de manipuler la collection résultant directement dans moins de requêtes et le code plus efficace. Compte tenu de l'auteur avec un grand nombre d'instances de livre associés si vous deviez écrire du code comme ce qui suit vous verriez un impact sur la performance:

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