2009-03-07 4 views
3

Этот пост является продолжением ответа на этот вопрос: Best method for storing a list of user IDs.Эффективная структура таблицы MySQL для рейтинговой системы

Я принял эпический совет Мехрдада Афшари по использованию нормализованного подхода к базе данных. Правильно ли настроены следующие таблицы для правильной оптимизации? Я новичок в эффективности MySQL, поэтому я хочу убедиться, что это эффективно.

Также, когда дело доходит до определения среднего рейтинга игры и общего количества голосов, я должен использовать следующие два запроса, соответственно?

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

ответ

6

средние голоса за игру: SELECT avg(vote) FROM votes WHERE gid = $gid;

количество голосов для игры: SELECT count(uid) FROM votes WHERE gid = $gid;

Поскольку у вас не будет ни одного пользователя или игрового ids меньше 0, вы можете сделать их целыми без знака (int(8) unsigned NOT NULL).

Если вы хотите обеспечить, что пользователь может сделать только один голос за игру, а затем создать первичный ключ на uid и gid в votes таблицы вместо просто нормального индекса.

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

Порядок первичного ключа полей (первый gid, то uid) очень важно, чтобы индекс сортируется по gid первым. Это делает индекс особенно полезным для выборок с заданным gid. Если вы хотите выбрать все голоса, предоставленные данным пользователем, добавьте еще один индекс с uid.

Я бы порекомендовал InnoDB для хранения, потому что, особенно в условиях высокой нагрузки, блокировки стола убьют вашу производительность. Для производительности чтения вы можете реализовать систему кеширования с использованием APC, Memcached или других.

0

Выглядит хорошо. Не забывайте индексы и внешние ключи. По моему опыту большинство проблем не возникает из-за не-продуманных проектов, а из-за отсутствия индексов и внешних ключей.

Кроме того, что касается выбора механизма хранения, я еще не видел причины (в достаточно сложном/размерном приложении) для того, чтобы не использовать innodb, а не только из-за транзакционной семантики.

+0

В настоящее время я не использую MyISAM, а не InnoDB. Вы бы рекомендовали использовать InnoDB. –

2

Выглядит хорошо.

я бы использовал users_id & games_id вместо GID и UID, который звучит как глобальный идентификатор и уникальный идентификатор

1

Что бы вы в конечном итоге делаете, убедитесь, что вы проверить его с большим набором данных (даже если вы не планируете иметь огромное количество пользователей)

Написать скрипт, который генерирует 100000 игр, 50000 пользователей и миллион голосов. Может быть немного чрезмерным, но если ваши запросы не занимают часы с таким количеством элементов, это никогда не будет проблемой

0

Возможно, вы захотите добавить столбец voted_on (DATETIME). Таким образом, вы могли бы, скажем, увидеть тенденцию игры в определенный промежуток времени, или на всякий случай когда-нибудь проголосовал за спам, вы можете точно удалить нежелательные голоса.