2009-03-06 9 views
4

Je travaille actuellement sur un système d'évaluation PHP/MySQL. Pour que l'utilisateur puisse noter l'utilisateur doit se connecter. Chaque utilisateur a un "UID" unique. Il y aura plusieurs instances de notation sur le site (une pour chaque jeu, dans mon cas) et j'ai besoin d'un moyen efficace de stocker une liste d'UID dans une rangée MySQL (une ligne MySQL dans la table de notation pour chaque instance du système de notation) pour garder un décompte de qui a voté.Meilleure méthode pour stocker une liste d'ID utilisateur

J'ai vu dans d'autres systèmes que la liste est stockée dans un tableau PHP sérialisé. Chaque fois qu'un utilisateur vote, le tableau sérialisé doit être extrait, non sérialisé, le nouvel UID est inséré, le tableau est re-sérialisé et la ligne MySQL est UPDATEd. Chaque fois que la page est chargée, cette liste doit à nouveau être désérialisée et vérifiée pour voir si l'utilisateur consultant la page a déjà voté pour s'assurer que l'utilisateur ne votera pas deux fois.

Cela semble plutôt inefficace et lourd. Est-ce que MySQL a une fonction de liste intégrée pour aider ce processus à être plus efficace? Y at-il des moyens plus intelligents que je pourrais résoudre ce problème?

J'ai envisagé une alternative possible qui consiste à oublier la sérialisation et à stocker les UID dans un champ de type TEXT dans la base de données MySQL. Je voudrais juste ajouter un caractère non numérique après chaque UID (disons un point [.]). Pour ajouter une entrée d'utilisateur, je voudrais simplement concaténer l'UID à la fin du champ TEXT puis un point. En vérifiant si l'utilisateur a déjà voté je pourrais simplement "SELECT * FROM table WHERE votes = '% $ UID.%';". Est-ce que cela fonctionnerait plus efficacement ou y a-t-il une façon plus élégante de faire le travail?

poste de suivi de la structure de la table ... Efficient MySQL table structure for rating system

Répondre

17

Il est inefficace. Ce que vous avez ici en termes relationnels est une relation plusieurs-à-plusieurs entre les utilisateurs et les jeux. Un utilisateur peut voter sur de nombreux jeux. Un jeu peut être voté par de nombreux utilisateurs. La solution pour cela est d'avoir une table de jointure:

USERS (uid, name, ...) 
GAMES (gid, name, ...) 
VOTES (id, uid, gid, ...) 

Où UID et GID sont des clés étrangères de retour à leurs tables respectives.

Si quelqu'un vote, insérez un enregistrement dans VOTES.

Pour obtenir une liste des votes pour un jeu:

$get = mysql_query("SELECT * FROM votes WHERE gid = $game_id"); 
... 

Pour obtenir une liste des votes de l'utilisateur:

$get = mysql_query("SELECT * FROM votes WHERE uid = $user_id"); 
... 

et ainsi de suite. Ne pas joindre un tableau et le stocker dans une seule colonne. Tu as raison d'éviter ça.

+0

Il semble que vous et Mehrdad suggériez la même approche. Je le fais de cette façon. Ma seule préoccupation est la taille de la table VOTES. Il est concevable qu'il puisse y avoir des votes <# games x # users> dans cette table. Est-ce que cela devrait faire peur à mon administrateur de plan d'hébergement partagé? –

+1

De manière réaliste, une taille de table doit atteindre des millions avant même que vous ayez besoin de considérer le «partitionnement» (la division des données essentiellement). L'approche de l'implosion d'un tableau aura des lignes mais des frais généraux significativement plus élevés pour la lecture et l'écriture. – cletus

+1

Si vous faites les requêtes listées ci-dessus, assurez-vous d'indexer la table avec * à la fois * uid et gid pour accélérer les requêtes. C'est la plus grande pénalité de cette approche: vous avez besoin de plusieurs index. – slacy

4

Dans une base de données normalisée, vous devez le stocker dans une table de jonction:

UserRatings 
------------- 
RatingID int 
UserID int 
UserVote int 

Je ne sais pas quels sont vos requêtes. Selon l'application, cela peut ne pas avoir les performances acceptables. Cependant, dans les deux cas, je suggère que vous alliez avec l'approche normalisée, la référence, et dénormaliser seulement si approprié.

Questions connexes