2011-01-11 3 views
1

La table de mes utilisateurs dans la base de données devient de plus en plus grande (en termes de colonnes et non de lignes) et par conséquent ralentit diverses zones de mon site. C'est parce qu'il essaye de saisir chaque colonne de la table de l'utilisateur chaque fois qu'il fait une jointure contre lui. Je pensais que je garderais tous les champs communs dans la table de l'utilisateur et ensuite mettre les champs supplémentaires dans des tableaux séparés. Par exemple, dire que j'ai les tableaux ci-dessous dans ma base de données:Découper une table pour améliorer les performances

Users: 

- UserID (PK, Identity) 
- UserName 
- Password 
... 

UsersActivity: 

- UserID (PK, FK) 
- LastActivityDate 
- LastLoginDate 
... 

UsersPreferences: 

- UserID (PK, FK) 
- HtmlEmail 
- HideEmail 
... 

Avec les entités suivantes:

public class User { 
    public virtual int UserID { get; set; } 
    public virtual string UserName { get; set; } 
    public virtual string Password { get; set; } 
    public virtual UserActivity Activity { get; set; } 
    public virtual UserPreferences Preferences { get; set; } 
} 

public class UserActivity { 
    public virtual User User { get; set; } 
    public virtual DateTime LastActivityDate { get; set; } 
    public virtual DateTime LastLoginDate { get; set; } 
} 

public class UserPreferences { 
    public virtual User User { get; set; } 
    public virtual bool HtmlEmail { get; set; } 
    public virtual bool HideEmail { get; set; } 
} 

Je me demandais quelle est la meilleure façon de mapper ce pour des performances optimales? J'ai pensé que je pouvais faire un mapping one-to-one sur les propriétés Activity et Performance dans l'entité User. Cependant, autant que je sache, le mappage un-à-un ne supporte pas le chargement paresseux et cette approche finirait par être plus lente. J'ai également étudié le mappage des composants et je ne savais pas trop si je pouvais le mapper dans une table séparée (corrigez-moi s'il serait préférable de le conserver dans la même table) et si les composants supportaient le chargement paresseux. Avant de procéder à un refactoring lourd de mon application, j'ai pensé que j'aurais l'opinion de quelqu'un qui aurait pu le faire. Vraiment apprécier l'aide.

Merci

Edit: je trouve que vous pouvez charger un paresseux à une relation aussi longtemps qu'il est nécessaire/contrainte. Ce qui est mon cas. Par conséquent, je suis allé de l'avant et exécutaient les instructions dans l'article suivant:

http://brunoreis.com/tech/fluent-nhibernate-hasone-how-implement-one-to-one-relationship/

Le problème est maintenant que je reçois l'erreur:

NHibernate.Id.IdentifierGenerationException: NHibernate.Id.IdentifierGenerationException: null ID généré pour: UserActivity.

+0

J'ai posté une question de suivi qui est plus spécifique à la cartographie d'une relation un-à-un que vous pouvez trouver ici http://stackoverflow.com/questions/4660160/map-one-to-one-relationship -doesnt-allow-insertion. Je vais mettre à jour cette question avec mes conclusions dans un proche avenir. – nfplee

Répondre

0

Dans NHibernate 3.0, la relation un-à-un prend en charge le chargement paresseux.

Et je pense qu'il est préférable d'utiliser Component avec la combinaison de la propriété Lazy. Ensuite, vous serez en mesure de laisser toutes les propriétés dans une table et de ne pas les charger toutes en même temps.

+0

Je ne suis pas en mesure de passer à la version 3 atm. L'idée de composant va être ma solution de rechange si je ne peux pas obtenir une relation un-à-un fonctionnant. J'ai mis à jour ma question avec plus de détails sur les problèmes que j'ai avec le mappage un-à-un. J'utilise couramment le nhibernate mais l'équivalent en xml est très similaire. – nfplee

+0

La dernière version de NHibernate 3 semble avoir résolu les problèmes que j'avais et je suis maintenant en mesure de mettre à jour. – nfplee

0

Vous devez effectuer un profilage d'application supplémentaire afin de déterminer les raisons pour lesquelles vous rencontrez un problème de performance. Il est peu probable que cela soit dû au nombre de colonnes dans la liste de sélection. Vous avez probablement un N+1 select problem. Cela dit, il y a beaucoup de bonnes raisons d'utiliser un objet léger, donc vous devriez envisager d'implémenter un DTO (objet de transfert de données) pour cela.

+0

J'ai mis à jour ma question avec plus d'informations. Ce n'est pas un problème n + 1 sélectionné. J'essaie d'éviter mes requêtes en saisissant tous les champs dans une instruction select car ils ne sont pas toujours nécessaires. – nfplee

+0

Je suis toujours très sceptique que la sélection de chaque champ est la cause première de votre problème de performance. –

+0

Il y a d'autres problèmes aussi bien que je suis sûr mais disons que ma table d'utilisateurs a 2 champs Biographie (texte) et MetaDescription (texte) qui sont seulement montrés sur le profil d'utilisateurs. Je n'ai pas besoin de retirer cette information chaque fois que j'essaie d'accéder à la table des utilisateurs. Je pourrais charger paresseux la propriété mais pour chaque propriété vous obtenez un coup additionnel sur la base de données. En les mettant dans leur propre table, cela me permet de regrouper ces propriétés. – nfplee

Questions connexes