1

我正在做一个项目,到目前为止有 7000 多行排行榜数据,其中包含名称、id、分数和排名。它在不断扩展,我目前遇到了一个问题,即每次有人发布新分数时尝试更新所有内容后服务器超时。

目前,我正在使用 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()); 
    }
4

3 回答 3

1

为什么需要存储排名?那是一种非规范化形式,您真的需要它还是因为预期需要它而实施了该步骤?

例如,请参阅此解决方案:

http://thinkdiff.net/mysql/how-to-get-rank-using-mysql-query/

也许试试这如何执行?

此外,如果您看到他制作的示例,您可以在查询中使用变量。这也将允许您将此更新语句组合在一个查询中。循环中的查询是一个很难的查询,不幸的是,它甚至几乎不会真正有效。

于 2012-07-03T07:33:52.703 回答
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 来尝试这个,所以如果这根本不可行,我将删除它。

于 2012-07-03T04:32:28.240 回答
0

快速搜索一下 mysql 的“CASE”。

不过,您很可能会在这里找到答案:Stackoverflow #9346755

本质上,你有一个 SQL 行,它有它自己的“内部 switch 语句”。当给定字段具有特定值时,您只需要告诉它要做什么。例如。在上面的链接中,它说..

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 数组的末尾。

编辑: 但请记住,上述内容仅在您基于另一个字段(例如键)更新一个字段时才有效。

于 2012-07-03T05:04:58.623 回答