2009-03-07 12 views
3

Ce message est une suite de cette réponse à cette question: Best method for storing a list of user IDs.Structure efficace de la table MySQL pour le système de notation

J'ai pris le conseil épique de Meethdad Afshari et de Cletus d'utiliser une approche de base de données normalisée. Les tableaux suivants sont-ils correctement configurés pour une optimisation correcte? Je suis un peu nouveau à l'efficacité de MySQL, donc je veux m'assurer que c'est efficace.

Aussi, quand il s'agit de trouver la note moyenne pour un jeu et le nombre total de votes devrais-je utiliser les deux requêtes suivantes, respectivement?

SELECT avg(vote) FROM votes WHERE uid = $uid AND gid = $gid;  
SELECT count(uid) FROM votes WHERE uid = $uid AND gid = $gid; 

CREATE TABLE IF NOT EXISTS `games` (
    `id` int(8) NOT NULL auto_increment, 
    `title` varchar(50) NOT NULL, 
    PRIMARY KEY (`id`) 
) AUTO_INCREMENT=1 ; 

CREATE TABLE IF NOT EXISTS `users` (
    `id` int(8) NOT NULL auto_increment, 
    `username` varchar(20) NOT NULL, 
    PRIMARY KEY (`id`) 
) AUTO_INCREMENT=1 ; 


CREATE TABLE IF NOT EXISTS `votes` (
    `uid` int(8) NOT NULL, 
    `gid` int(8) NOT NULL, 
    `vote` int(1) NOT NULL, 
    KEY `uid` (`uid`,`gid`) 
) ; 

Répondre

6

votes moyenne pour un jeu: SELECT avg(vote) FROM votes WHERE gid = $gid;

nombre de voix pour un jeu: SELECT count(uid) FROM votes WHERE gid = $gid;

Comme vous n'aurez pas d'identifiant d'utilisateur ou de jeu plus petit que 0, vous pourriez en faire des entiers non signés (int(8) unsigned NOT NULL).

Si vous souhaitez appliquer qu'un utilisateur ne peut faire un seul vote pour un jeu, puis créer une clé primaire sur uid et gid dans la table votes au lieu d'un indice normal.

CREATE TABLE IF NOT EXISTS `votes` (
    `uid` int(8) unsigned NOT NULL, 
    `gid` int(8) unsigned NOT NULL, 
    `vote` int(1) NOT NULL, 
    PRIMARY KEY (`gid`, `uid`) 
) ; 

L'ordre des champs de clé primaire (premier gid, puis uid) est important pour l'indice est triée par gid premier. Cela rend l'index particulièrement utile pour les sélections avec un gid donné. Si vous voulez sélectionner tous les votes d'un utilisateur donné, ajoutez un autre index avec juste uid.

Je recommanderais InnoDB pour le moteur de stockage parce que dans les réglages de charge élevés, les verrous de table vont tuer votre performance. Pour lire les performances, vous pouvez implémenter un système de mise en cache en utilisant APC, Memcached ou autres.

0

Apparemment bien. Ne pas oublier les indices et les clés étrangères. D'après mon expérience, la plupart des problèmes ne découlent pas de conceptions qui ne sont pas si bien conçues, mais du manque d'indices et de clés étrangères.

En ce qui concerne la sélection du moteur de stockage, je n'ai pas encore trouvé de raison (dans une application raisonnablement complexe/de taille) de ne pas utiliser innodb, pas seulement à cause de la sémantique transactionnelle.

+0

Actuellement, je n'utilise pas MyISAM et pas InnoDB. Recommanderiez-vous InnoDB. –

2

Ça a l'air bien.

Je l'ai utilisé users_id & games_id au lieu de GID et uid qui sonne comme id global et unique id

1

Tout ce que vous finissez par faire, assurez-vous de le tester avec un grand ensemble de données (même si vous ne prévoyez pas d'avoir un grand nombre d'utilisateurs)

Ecrire un script qui génère 100.000 jeux, 50 000 utilisateurs et un million de votes. Peut être légèrement excessif, mais si vos requêtes ne prennent pas des heures avec ce nombre d'éléments, ce ne sera jamais un problème

0

vous pouvez également ajouter une colonne voted_on (DATETIME). De cette façon, vous pourriez, disons, voir la tendance d'un jeu dans un certain laps de temps, ou juste au cas où un jour un spam de vote se produirait, vous pourriez supprimer les votes non désirés avec précision.