MySQL - 排名数百万条

时间:2016-12-05 20:21:02

标签: php mysql database laravel

我正在开展一个项目,现在我正在实施一个排行榜。在开始研究之前,我需要一些建议来更好地练习我的排行榜结构。

首先,排行榜将显示在两个页面上,一个位于每个玩家的主页上,其中包含前10个团队(所有玩家共有10个团队),另一个排行榜将是在排行榜的页面中,所有团队都有排序功能。

每行排行榜的结构如下:
•排名位置
•团队名称
•团队价值
•团队赢得的比赛总数 •球队击败的总比赛次数 •团队抽签的总数 •团队目标的总和 •球队承认的目标总和 •团队的最后4场比赛结果

以下是我的数据库表

挑战表

CREATE TABLE `challenges` (
  id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  'challenge_date` datetime NOT NULL,
  `status` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `challanges_id_index` (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

挑战结果

CREATE TABLE `challenges_results` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `challenge_id` int(11) NOT NULL,
  `team_id` int(11) NOT NULL,
  `goals` int(11) NOT NULL,
  `result` char(1) DEFAULT NULL,
  `challenge_date` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在挑战结果中,结果列可以是W代表胜利,D代表平局,L代表失败

团队价值

CREATE TABLE `team_values` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `team_id` int(11) DEFAULT NULL,
  `value` double(15,8) DEFAULT '1500.00000000',
  `created_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

团队

CREATE TABLE `teams` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `avatar` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `founded` date NOT NULL,
  `residense_city_id` int(10) unsigned NOT NULL,
  `slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `primary_color` char(10) COLLATE utf8_unicode_ci NOT NULL,
  `secondary_color` char(10) COLLATE utf8_unicode_ci NOT NULL,
  `status` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `teams_slug_unique` (`slug`),
  KEY `teams_id_index` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

一个团队可以拥有多个值(teams_values),但只会显示最近的值。 一个团队可以面临许多挑战。 一个团队可以从不同的挑战中获得许多成果。

排行榜将如下工作。团队将使用teams_values表中的最高值进行排序。每当团队遇到挑战时,就会计算并存储该值。

如果两个或更多团队具有相同的价值,我们需要应用以下三个规则。规则也需要逐个执行,例如,如果我运行第一个规则并且仍然存在与价值和目标相等的团队,那么我将应用第二个规则,依此类推。 •最佳进攻(得分更高的目标数)
•最佳防守(减少失球次数)
•在他们之间的比赛中获胜最多的团队

所以我提出了三个解决方案,但我还不知道哪一个更好,如果有三个更好。

我的第一个选项是使用内连接,联合等选项来从表中收集信息并在同一SQL查询上应用规则。所以每次我想查看排行榜时,我都会执行这个SQL。这个解决方案的问题在于,我不知道如果我们希望排行榜始终与最新结果保持同步,效果会有多大。因为成像每天有10k访客,每个人都在执行此查询。

第二个选项是收集信息,如果有重复值,我将使用PHP获取重复的团队,应用规则,然后根据规则的结果轻扫阵列中的团队。从表现网站我不知道这个选项的效果如何。

第三个解决方案是创建另一个名为leaderboard的表,我将存储所有这些信息以防团队不存在或者如果基于最新挑战的结果存在,我将更新记录,例如,如果增加目标,球队得分。然后我将仅使用排行榜表来过滤数据并打印团队的排名。我相信这个选项更好,因为我只需要处理一个表,我只会在团队完成挑战时更新记录。

我们将使用缓存,但是现在我们认为排行榜应该始终是最新的,而不是每天更新一次。

哪一个是更好的解决方案,为什么以及为了获得更好的解决方案,我可以提出建议。谢谢

1 个答案:

答案 0 :(得分:0)

由于您在虚拟专用服务器上的共享帐户上运行,因此理论上可能会遇到您争用服务器资源,磁盘使用情况,内存的情况用法,cpu处理能力。

首先,尝试在MySQL中进行所有数据库计算,并且只有在完成对它们的所有操作后才将数据返回给PHP。 MySQL针对这项工作进行了优化,而PHP在一般计算问题上更胜一筹。

从服务器上卸下一些负载的一个选择是使用PHP创建一个可在浏览器中查看的网页,每次更新排行榜时。这样,每次需要更新排行榜时,您只需执行一次计算。

如果我正在构建系统并且系统永远不会达到企业级别,而是保持小型和功能,我会尽早编写PHP脚本,因为您可以单独节省大量处理能力

对于它的价值,如果服务器配置得当,你不应该担心每天获得10k用户请求,除非你的代码写得非常糟糕。

编辑:作为事后的想法,您可以安装像https://memcached.org/这样的程序,它将您的SQL数据缓存在RAM中。像LiveJournal和Wordpress这样的网站使用它,但是您需要以适合其他vps用户的方式对其进行配置,除非该框具有非常高的规格。