1

私はこれまでに、名前、ID、スコア、およびランクを含む 7000 行以上のリーダーボード データを持つプロジェクトに取り組んでいます。それは継続的に拡大しており、私は現在、誰かが新しいスコアを投稿するたびにすべてを更新しようとした後、サーバーがタイムアウトするという障害に遭遇しました.

現在、ループした 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()); 
    }
4

3 に答える 3

1

なぜランクを保存する必要があるのでしょうか? これは非正規化形式です。本当に必要でしたか、それとも必要になると予想されていたためにそのステップを実装しましたか?

たとえば、このソリューションを参照してください。

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

多分これがどのように機能するか試してみませんか?

また、彼が作成した例を見ると、クエリで変数を使用できます。これにより、この update ステートメントを 1 つのクエリに結合することもできます。ループ内のクエリは難しいものであり、残念ながら本当に効率的でさえありません。

于 2012-07-03T07:33:52.703 に答える
0

このすべてを1つのクエリで実行できると思います。

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

基本的に、独自の「内部スイッチステートメント」を持つ 1 つの 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 配列の最後に到達するまで繰り返します。

編集: ただし、上記は別のフィールド(キーなど)に基づいて1つのフィールドを更新している場合にのみ機能することに注意してください。

于 2012-07-03T05:04:58.623 に答える