4

すべてのユーザーが毎日更新されるスコアを持つサイトを作成しています。このスコアから簡単にランキングを作成できますが、週や月などの「ホット」リストを作成できるようにしたいと思います。

私のブルートフォースの設計は、すべてのユーザーに対して毎日行われ、スコアを計算して「スコア」テーブルに入れます。したがって、毎日、スコアテーブルはユーザーの数だけ増加します。どの期間でも、スコアデルタでユーザーをランク付けできました。

これは技術的にはうまくいくと思いますが、これを行うにはもっと洗練された方法が必要だと思いますよね?か否か?私は、他のサイトがそれをしている方法ではありえない、何人のユーザーがいるのかによって毎日増加するスコアテーブルのように感じます。

4

2 に答える 2

4

スコアのスナップショットをまったく保存しないことで、最大限の柔軟性が得られます。代わりに、発生した増分スコアを記録します。

このようなテーブルがある場合:

ユーザー

  • ユーザーID
  • 名前
  • personal_high_score
  • {ユーザーごとに1回保存するその他のもの}

SCORE_LOG

  • score_log_id
  • user_id(FKからUSER)
  • 日付時刻
  • scored_points

これで、次のような簡単なクエリを使用して、任意の時点でのユーザーの累積スコアを取得できます。

select sum(scored_points)
from SCORE_LOG
where user_id = @UserID
  and date_time <= @PointInTime

また、次のような期間でトップランクのスコアラーを簡単に取得できます。

select
  user_id
, sum(scored_points)
from SCORE_LOG
group by
  user_id
where date_time >= @StartOfPeriod
  and date_time <= @EndOfPeriod
order by
  sum(scored_points) desc
limit 5

本番環境に移行して、実際にパフォーマンスの問題が発生していることに気付いた場合は、意味のある統計のスナップショットを非正規化することを検討できます。これらのスナップショット統計の問題は、ソースデータと同期しなくなる可能性があるため、スナップショットを定期的に再計算するための戦略が必要になることです。

2つの真実の情報源がある場合、最終的に2つの「真実」になってしまうというのは、ほとんど真実です(マーフィーの法則の結果と考えてください)。

于 2012-10-21T23:09:31.700 に答える
2

Barrankaは彼のコメントで正しい方向に進んでいました。可能な限り、データを複製していないことを確認する必要があります。

ただし、一部の古いユーザースコアに戻すことができるようにしたい場合、または1日を選び出し、特定の時点で誰がトップだったかを確認できるようにする場合、つまり動的レポートを作成する場合は、各レコードを個別に記録する必要があります。デート。SQLを介して既存のユーザーデータから日次スコアを推定し、必要なときにいつでもテーブルに入力できるため、このための個別のテーブルがあると便利です。

あなたが持っている決定は、あなたが履歴に何人のユーザー記録を維持したいか、そしてどれくらいの期間であるかです。「ホットリスト」が上位5人のユーザーになるという考えで、以下を作成しました。CRONジョブまたはスケジュールされたタスクを毎日/月に実行して、挿入を実行し、非常に古いデータをクリーンアップすることもできます。

ユーザー

  • id
  • ユーザー名
  • スコア

score_ranking

  • id
  • user_id(すべてのユーザー情報ではなくidを使用して正規化します)
  • score_at_the_time
  • date_of_ranking

したがって、単一のデータランキングを生成するには、このテーブルに挿入できます。何かのようなもの:

INSERT INTO
  `score_ranking` (`user_id`, `score_at_the_time`, `date_of_ranking`)
SELECT
  `id`, `score`, CURDATE()
FROM
  `users`
ORDER BY
  `score` DESC
LIMIT
 5

次に、特定の日付(または日付範囲)のデータを読み取るには、次のようにします。

SELECT * FROM score_ranking 
WHERE date_of_ranking = 'somedate' 
ORDER BY score_at_the_time DESC
于 2012-10-21T16:35:44.380 に答える