用于评级系统的高效 MySQL 表结构

发布于 2024-07-15 11:02:33 字数 903 浏览 9 评论 0原文

这篇文章是此已回答问题的后续内容:最佳方法用于存储用户 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

稀香 2024-07-22 11:02:33

游戏的平均票数:SELECT avg(vote) FROM votes WHERE gid = $gid;

游戏的票数:SELECT count(uid) FROM votes WHERE gid = $gid;< /code>

由于您不会有任何小于 0 的用户或游戏 ID,您可以将它们设置为无符号整数 (int(8) unsigned NOT NULL)。

如果您想强制用户只能对游戏进行单次投票,请在 votesuid 和 gid 的主键> 表而不是普通的索引。

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 或其他实现缓存系统。

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 and gid in the votes table instead of just a normal 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`)
) ;

The order of the primary key's fields (first gid, then uid) is important so the index is sorted by gid first. That makes the index especially useful for selects with a given gid. If you want to select all the votes a given user has made then add another index with just uid.

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.

憧憬巴黎街头的黎明 2024-07-22 11:02:33

看起来不错。

我会使用 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

生生漫 2024-07-22 11:02:33

无论您最终做什么,请确保使用大型数据集对其进行测试(即使您不打算拥有大量用户)

编写一个生成 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

岁吢 2024-07-22 11:02:33

到目前为止看起来不错。 不要忘记索引和外键。 根据我的经验,大多数问题并不是由于考虑不周的设计而引起的,而是由于缺乏索引和外键而引起的。

另外,关于存储引擎的选择,我还没有看到不使用 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.

舂唻埖巳落 2024-07-22 11:02:33

您可能还想添加一个 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文