8

最も人気のある今日、今週、今月の 3 つのフィールドのいずれかで順序付けされたエントリを表示するシステムがあります。エントリが表示されるたびに、スコアが 1 ずつ増加するため、順序が変更されます。

したがって、エントリ 1 が新しく、今日 10 回表示された場合、そのスコアは次のようになります。

Today: 10
Week: 10
Month: 10

現在のソリューション

現時点では、各エントリに 3 つのフィールドが関連付けられています。1 つは今日用、もう 1 つは今週用、もう 1 つは今月用です。エントリが表示されるたびに、3 つのスコアすべてが 1 ずつ増加します。

その日の終わりに、その日のスコアは 0 にリセットされます。現在の週の終わりに、その週のスコアは 0 に設定され、現在の暦月の終わりに、その月のスコアは 0 に設定されます。

問題

これは機能し、ほとんどスペースを使用しませんが、次の 2 つの理由から理想的ではありません。

1) 現在の期間 (日、週、月) の終わりに、その値は一度に 0 にリセットされます。つまり、毎日 00:00:00 にランキングがすべてリセットされ、すべての毎日のスコアが 0 に設定されます。週末と月末も同様です。毎月 1 日の 00:00:00 にすべてのスコアが 0 に設定され、既存のランキング データがすべて失われます。

2) 通常、月末は 1 週間 (月~日) に含まれるため、月間スコアはその週にリセットされ、週間スコアが月間スコアよりも高くなります。

考えられる解決策

現在の時間インデックスに基づいて現在の日、週、月のスコアを計算するために使用される、月のすべての時間にローリング時間カウンターを使用できます。

Array size = 31 * 24 = 744 int16 values

したがって、1 日の午前 4 時のビューは時間単位で配置されます[4]。

hours[4]++

次に、統計計算機は今日を最後の 24 値の合計として使用し、今週のスコアは最後の (24*7) 値の合計になります。最後に、今月は最後の (24*31) 値の合計になります。

ソリューションの問題

ソリューション 1 の主な問題は、ディスク/メモリの要件です。現在のソリューションでは 3 つの 32 ビット値を使用していましたが、744 個の 32 ビット値を使用するようになりました。それらをin16に変更しても、エントリごとにより多くのメモリを使用することになります

Memory per Entry = 3 * 4 bytes = 12 bytes (Existing)
Memory per Entry = 744 * 2 = 1,488 bytes (possible solution)

このソリューションにより、エントリごとのメモリ使用量が 12400% 跳ね上がりました!!

エントリごとに 1.5k を使用せずに、現在のソリューションの問題を解決する別のソリューションを誰かが提案できますか?

どうもありがとう!

4

3 に答える 3

6

これは実際、データを効果的にグループ化し、必要な情報をすべて保持する方法の一般的な問題です。

まず第一に:自分のやり方でやってみましたか?ストレージが本当に不足していましたか?あなたの解決策は合理的なようです。

どのように私はそれを行うだろう

データを保持するためにデータベースを使用していると思います。

hourly1 つは統計用、もう 1 つは統計用の 2 つの別個のテーブルを作成しdailyます。各記事は、そのデータベースに 1 時間ごとに 1 行ずつ、正確に 24 行あります。それはhourly統計に使用されます。特定の行を更新するには、時間 (0-23) と entry_id を知るだけで済みます。UPDATE count=count+1 WHERE hour=11 AND entry_id = 18164;

entry_id foreign key | hour integer | count integer
---------------------+--------------+--------------
1                    | 0            | 123
1                    | 2            | 1712
...

現在の毎日の統計は、真夜中頃 (またはアプリの実行が最も少ない時間) に計算されるか、必要に応じて合計されます。いずれにせよ、1 日に 1 回、すべての時間別データの合計を作成し、その合計をdaily統計テーブルに挿入する必要があります。

entry_id foreign key | day date   | count integer
---------------------+------------+--------------
1                    | 2013-07-03 | 54197
1                    | 2013-07-04 | 66123
...

31 (30/29/28) 日より古い各エントリは削除する必要があります。合計または年間の統計が必要な場合

利点

  • 完全な 1 時間ごとの統計よりも保持するデータが少なくなります: 24+31
  • entry_id と hour でインデックスが作成されている場合、1 時間ごとのテーブルの合計は高速である必要があります
  • ソリューションよりも少ないメモリ使用量

短所

  • 統計を毎日更新するために必要な追加のスクリプト/トリガー/ジョブ
  • それを実装するには、ソリューションよりも多くの作業が必要です
于 2013-07-04T09:31:03.150 に答える
2

たぶん、ある種の減衰が役立つかもしれません。TodayYesterdayThisWeek、 、LastWeekThisMonthは6 つの変数が必要ですLastMonth

次に、最終的な評価 (たとえば毎日) は次のように計算できますToday + Yesterday * attenuation( current_time - start_of_the_day )

減衰は のようなもの1 / (1 + k * time)で、k最後の日の評価を収縮させる速度に応じて調整できます。

更新:新しいエントリが 1 日に 123 回表示されたと考えてください。そして、いくつかの数値に到達するまでの時間を秒単位で測定してみましょう。23:59 の etrys の評価は です123 + 0 * 1 / (1 + k * 86340)^2 = 100

真夜中のTodayカウンターは次のようになりYesterdayます。

0 + 123 * 1 / ( 1 + k * 0)^2 = 123

正午までにエントリのビューが 89 回増えたとします。

89 + 123 * 1 / ( 1 + k * 43200 )^2 = ?

さて、それはを選択する良い時期kです。古いビューを 12 時間で 4 回フェードする場合はk1/43200. 100回フェードインしたい場合 - 9/43200。この場合:

89 + 123 * 1 / ( 1 + 9 )^2 = 90.23

そして23時59分まで。エントリーでさらに 60 回のビューを獲得しましょう

149 + 123 * 1 / ( 1 + (9/43200) * 86340 )^2 ~= 149.002

そのため、昨日のビューは、24 時間で評価への影響をほぼ完全に失いました。もちろんk、あなたのニーズに最も合うように、一般的にまたは減衰式で遊ぶことができます。これはほんの一例です。

于 2013-07-04T09:35:45.763 に答える
2

1つの簡単な解決策は

Use an array of 31.
Today - the last value
This Week score would be the sum of the last 7 values.
This Month would be the sum of the last 31 values.

At the end of each day, shift the whole array values by 1 to accommodate new value.

ご意見に関しましては、

Use another array of size 24 to store hours visit count.
Today - Sum of all elements of Array2
This Week score would be the sum of the last 7 values of Array1.
This Month would be the Sum of all elements of Array1.

At the end of each day, shift the whole array values of Array1 by 1
to accommodate new value. Last day visit count = Sum of all elements of Array2
于 2013-07-04T09:23:18.067 に答える