2009-03-07 11 views
3

Dieser Beitrag ist eine Follow-up dieser beantworteten Frage: Best method for storing a list of user IDs.Effiziente MySQL-Tabellenstruktur für Bewertungssystem

Ich nahm Cletus und Mehrdad Afshari epischen Rat der Verwendung einer normalisierten Datenbank-Ansatz. Sind die folgenden Tabellen ordnungsgemäß für die richtige Optimierung eingerichtet? Ich bin etwas neu in MySQL Effizienz, also möchte ich sicherstellen, dass dies effektiv ist.

Auch, wenn es darum geht, die durchschnittliche Bewertung für ein Spiel und die Gesamtzahl der Stimmen zu finden sollte ich jeweils die folgenden zwei Abfragen verwenden?

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`) 
) ; 

Antwort

6

Durchschnitt Stimmen für ein Spiel hätte: SELECT avg(vote) FROM votes WHERE gid = $gid;

Anzahl der Stimmen für ein Spiel: SELECT count(uid) FROM votes WHERE gid = $gid;

Da Sie keine Benutzer- oder Spiel-IDs kleiner als 0 haben, könnten Sie sie zu vorzeichenlosen Ganzzahlen machen (int(8) unsigned NOT NULL).

Wenn Sie erzwingen mögen, dass ein Benutzer nur eine einzige Stimme für ein Spiel machen, erstellen Sie einen Primärschlüssel über uid und gid in dem votes Tisch statt nur einen normalen Index.

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`) 
) ; 

Die Reihenfolge der Primärschlüssel der Felder (erstes gid, dann uid) ist wichtig, damit der Index von gid ersten sortiert ist. Das macht den Index besonders nützlich für Selects mit einem gegebenen gid. Wenn Sie alle Stimmen eines bestimmten Benutzers auswählen möchten, fügen Sie einen weiteren Index mit nur uid hinzu.

Ich würde InnoDB für Speicher-Engine empfehlen, weil vor allem in Hochlast-Einstellungen die Tabelle Sperren Ihre Leistung zu töten. Zur Leseleistung können Sie ein Caching-System mit APC, Memcached oder anderen implementieren.

0

Sieht gut aus so weit. Vergessen Sie nicht Indizes und Fremdschlüssel. Nach meiner Erfahrung entstehen die meisten Probleme nicht aus nicht so gut durchdachten Entwürfen, sondern aus dem Fehlen von Indizes und Fremdschlüsseln.

Auch in Bezug auf die Storage-Engine-Auswahl habe ich noch einen Grund zu sehen (in einer einigermaßen komplexen/Größe App) für die Verwendung von innodb, nicht nur wegen transaktionaler Semantik.

+0

Derzeit verwende ich nicht MyISAM und nicht InnoDB. Würden Sie InnoDB empfehlen? –

2

Sieht gut aus.

I users_id & games_id anstelle von gid und uid, die wie die globalen ID-Sounds und eindeutige ID

1

Was auch immer Sie bis am Ende tun, stellen Sie sicher, dass Sie es mit einem großen Daten-Set-Test (auch wenn Sie eine große Anzahl von Benutzern planen nicht auf mit)

ein Skript schreiben, die 100.000 Spiele erzeugt 50.000 Nutzer und eine Million Stimmen. Möglicherweise etwas übertrieben, aber wenn Ihre Fragen nicht Stunden mit dieser Anzahl von Elementen dauern, wird es nie ein Problem sein

0

Sie möchten vielleicht auch eine voted_on (DATETIME) Spalte hinzufügen. Auf diese Weise könnten Sie zum Beispiel den Trend eines Spiels in einer bestimmten Zeitspanne sehen, oder nur für den Fall, dass eines Tages ein Wahl-Spam passieren sollte, könnten Sie unerwünschte Stimmen genau löschen.

Verwandte Themen