我正在开发一个项目,到目前为止已有7000多行排行榜数据,其中包含名称,ID,分数和排名。它不断扩大,我现在遇到了一个障碍,在每次有人发布新分数时尝试更新所有内容后服务器会超时。
目前我正在使用带有查询和循环execute()调用的PDO。有没有明显更快的方法(可能在一个mySQL查询中)?或者,您对如何处理更新排行榜有任何建议吗?
$stmt = $dbh->prepare("SELECT * FROM high_scores ORDER BY score DESC");
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$results = $stmt->fetchAll();
//
$numItems = count($results);
// is this OK or a no-no?
try {
$stmt = $dbh->prepare("UPDATE high_scores SET rank = :rank WHERE uid = :uid");
for($i=0; $i<$numItems; $i++){
$rank = $i + 1;
$uid = $results[$i]['uid'];
$stmt->execute(array(':rank' => $rank, ':uid' => $uid));
}
return true;
} catch (PDOException $e) {
echo($e->getMessage());
}
答案 0 :(得分:1)
为什么你需要存储等级?这是一种非规范化形式,你真的需要它还是你实现了那个步骤,因为它需要它?
例如,请参阅此解决方案:
http://thinkdiff.net/mysql/how-to-get-rank-using-mysql-query/
也许可以尝试一下它的表现?
此外,如果您看到他创建的示例,您可以在查询中使用变量。这也将允许您将此更新语句组合在一个查询中。循环中的查询很难,不幸的是,它甚至不会真正有效。
答案 1 :(得分:0)
我认为您可以通过一个查询来完成所有这些操作,例如
UPDATE high_scores a SET rank = (SELECT count(uid) + 1 FROM high_scores b WHERE b.score > a.score) ORDER BY score DESC
不幸的是,我现在还没有可用的MySQL尝试这个,所以如果事实证明这根本不可行,我会删除它。
答案 2 :(得分:0)
快速浏览一下mysql的'CASE'。
你很可能会在这里找到答案:Stackoverflow #9346755
基本上,你有一个拥有它自己的“内部switch-statement”的SQL行。当给定字段具有特定值时,您只需告诉它该做什么。例如。在上面的链接中,它说... ..
When `id` is 1, then set the value to 12.
When `id` is 2, then set the value to 42.
etc.
您唯一关心的可能是7000多行。
但是,使用PHP,我将数据放在一个数组中,然后使用array_slice(),一次获取200/300条记录,设置SQL行,然后执行。然后获取下一个200/300记录并重复,直到它到达PHP数组的末尾。
修改强> 请注意,上述内容仅在您根据其他字段(例如密钥)更新ONE字段时才有效。