【问题标题】:Efficient MySQL table structure for rating system用于评级系统的高效 MySQL 表结构
【发布时间】:2023-03-14 14:06:01
【问题描述】:

这篇文章是这个已回答问题的后续:Best method for storing a list of user IDs

我接受了 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`)
) ;

【问题讨论】:

    标签: php mysql optimization performance project-planning


    【解决方案1】:

    一场比赛的平均票数:SELECT avg(vote) FROM votes WHERE gid = $gid;

    游戏票数:SELECT count(uid) FROM votes WHERE gid = $gid;

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

    如果您想强制用户只能为游戏投一票,请在 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 或其他方式实现缓存系统。

    【讨论】:

      【解决方案2】:

      看起来不错。

      我会使用 users_id 和 games_id 而不是 gid 和 uid,这听起来像是全局 id 和唯一 id

      【讨论】:

        【解决方案3】:

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

        编写一个脚本,生成 100,000 款游戏、50,000 名用户和 100 万张选票。可能有点过分,但如果您的查询不需要花费数小时来处理这么多的项目,那将永远不会成为问题

        【讨论】:

          【解决方案4】:

          目前看起来不错。不要忘记索引和外键。根据我的经验,大多数问题都不是由于设计不够深思熟虑,而是因为缺少索引和外键。

          此外,关于存储引擎的选择,我还没有看到不使用 innodb 的原因(在相当复杂/大小的应用程序中),而不仅仅是因为事务语义。

          【讨论】:

          • 目前我没有使用 MyISAM 而不是 InnoDB。你会推荐使用 InnoDB。
          【解决方案5】:

          您可能还想添加voted_on (DATETIME) 列。这样一来,您就可以看到某个游戏在某个时间跨度内的趋势,或者万一某天发生了垃圾投票,您可以准确地删除不需要的投票。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-12-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-02-03
            • 1970-01-01
            • 2018-07-12
            • 1970-01-01
            相关资源
            最近更新 更多