用于评级系统的高效 MySQL 表结构
这篇文章是此已回答问题的后续内容:最佳方法用于存储用户 ID 列表。
我采纳了 cletus 和 Mehrdad Afshari 关于使用规范化数据库方法的史诗般的建议。 下表是否正确设置以进行适当的优化? 我对 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`)
) ;
This post is a follow-up of this answered question: Best method for storing a list of user IDs.
I took cletus and Mehrdad Afshari's epic advice of using a normalized database approach. Are the following tables properly set up for proper optimization? I'm kind of new to MySQL efficiency, so I want to make sure this is effective.
Also, when it comes to finding the average rating for a game and the total number of votes should I use the following two queries, respectively?
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`)
) ;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
游戏的平均票数:
SELECT avg(vote) FROM votes WHERE gid = $gid;
游戏的票数:
SELECT count(uid) FROM votes WHERE gid = $gid;< /code>
由于您不会有任何小于
0
的用户或游戏 ID,您可以将它们设置为无符号整数 (int(8) unsigned NOT NULL
)。如果您想强制用户只能对游戏进行单次投票,请在
votes
uid 和gid
的主键> 表而不是普通的索引。主键字段的顺序(首先是
gid
,然后是uid
)很重要,因此索引首先按gid
排序。 这使得索引对于具有给定gid
的选择特别有用。 如果您想选择给定用户的所有投票,请添加另一个仅包含uid
的索引。我推荐 InnoDB 作为存储引擎,因为特别是在高负载设置下,表锁会降低你的性能。 对于读取性能,您可以使用 APC、Memcached 或其他实现缓存系统。
average votes for a game:
SELECT avg(vote) FROM votes WHERE gid = $gid;
number of votes for a game:
SELECT count(uid) FROM votes WHERE gid = $gid;
As you will not have any user or game ids smaller then
0
you could make them unsigned integers (int(8) unsigned NOT NULL
).If you want to enforce that a user can only make a single vote for a game, then create a primary key over
uid
andgid
in thevotes
table instead of just a normal index.The order of the primary key's fields (first
gid
, thenuid
) is important so the index is sorted bygid
first. That makes the index especially useful for selects with a givengid
. If you want to select all the votes a given user has made then add another index with justuid
.I would recommend InnoDB for storage engine because especially in high load settings the table locks will kill your performance. For read performance you can implement a caching system using APC, Memcached or others.
看起来不错。
我会使用 users_id & games_id 而不是 gid 和 uid,听起来像全局 id 和唯一 id
Looks good.
I would have used users_id & games_id instead of gid and uid which sounds like global id and unique id
无论您最终做什么,请确保使用大型数据集对其进行测试(即使您不打算拥有大量用户)
编写一个生成 100,000 个游戏、50,000 个用户和 100 万个选票的脚本。 可能有点过多,但如果您的查询不需要花费几个小时来处理这么多的项目,那么它永远不会成为问题
Whatever you end up doing, make sure you test it with a large data-set (even if you don't plan on having a huge number of users)
Write a script that generates 100,000 games, 50,000 users and a million votes. May be slightly excessive, but if your queries don't take hours with that number of items, it'll never be an issue
到目前为止看起来不错。 不要忘记索引和外键。 根据我的经验,大多数问题并不是由于考虑不周的设计而引起的,而是由于缺乏索引和外键而引起的。
另外,关于存储引擎的选择,我还没有看到不使用 innodb 的原因(在相当复杂/大小的应用程序中),而不仅仅是因为事务语义。
Looks good so far. Don't forget indices and foreign keys. In my experience most issues don't arise from not-so-well-thought-out designs but from the lack of indices and foreign keys.
Also, regarding the storage engine selection I have yet to see a reason (in a reasonably complex/sized app) for not using innodb, not just because of transactional semantics.
您可能还想添加一个
voted_on
(DATETIME) 列。 这样,您就可以看到某个游戏在特定时间段内的趋势,或者万一有一天发生垃圾投票,您可以准确删除不需要的投票。you might want to add a
voted_on
(DATETIME) column too. That way, you could, say, see a game's trend in a certain timespan, or just in case someday a vote spam happened, you could delete unwanted votes accurately.