1

私は Facebook のニュース フィード ウォールのようなものを達成しようとしており、データセット全体から N 個の結果を読み込み、最新の日付の降順から始めます。「さらに」をクリックすると、データセットを終了するまで、次の N が下に表示されます。

これを実現するための最適な設計を考え出すのに苦労しています。スケーラブルなエンタープライズ アプリケーションを構築するには、ステートレス Web サービスが唯一の方法であると常に言われてきました。つまり、私が理解しているように、ページへの最初の呼び出しでサーバー側にキャッシュされた結果オブジェクト全体を保持し、そこから N 個の結果を取得するだけです。後続の各 Web サービス呼び出しはノーノ​​ーですか?

その場合、 GetResults(int pageindex, int pagesize) のようなものが機能します....それが私がやろうとしていた方法ですが、呼び出しの間に誰かが新しいDBレコードを追加すると機能しないことに気付きました。たとえば、DB 内の 23 個のウォール フィード アイテムから始めて、一度に 10 個ずつ表示したいとします。

  • 最初の呼び出し、ページ 1、ページ サイズ 10 は、結果 14 ~ 23 (最新のものから順に) を返します。
  • その後、誰かが 2 つの新しい投稿を追加したため、DB には現在 25 件あります
  • 2 番目の呼び出し、ページ 2、ページ サイズ 10 は結果 6 ~ 15 を返します。そのうちの 2 つは最初の呼び出しで既に返されています。

したがって、基になるデータセットが呼び出し間で同じままであることを保証できないため、この相殺アプローチは機能しません。

混乱しています。どうすればこれを達成できますか?

編集:申し訳ありませんが、もう少し情報を提供してください。巨大なデータ テーブル ルックアップの問題を回避するために、最初に画面をロードするときに、そのユーザーの過去数日間のデータを「一時的な」テーブルに事前入力し、一度に 1 ページずつ結果を読み取るオプションを検討しました。その一時テーブルから読み込みを高速化し、読み込み時間を少し遅くします。次に、そのデータを使い果たしたら、次の期間 (たとえば 2 週間) を一時テーブルに取り込み、読み取りを続けます。

問題は、ユーザーがアイテムを「投稿」すると、検索条件に一致するユーザーによって自動的にピックアップされることです。たとえば、25 ~ 32 歳で、50 マイル以内にいる人に会いたいという基準がある場合、ニュース フィードを読み込むときに、基準に一致するすべてのユーザーからの投稿を表示する必要があります。動的な友達リストのようなものです。

これを達成する方法は、ログイン時にストアド プロシージャが実行され、すべてのユーザーを選択し、静的ルックアップ テーブル (郵便番号の距離など)、条件に一致するユーザーのリストをこの一時テーブルに保存して、投稿をフィルタリングしたりユーザーを検索したりする必要があるときにいつでも使用できるようにします。設定を更新すると、これも再計算されますが、設定を更新するか再ログインした場合のみです。したがって、サインアップした新しいユーザーは、次にログインするまで表示されません。これで問題ないと思います.

ニュース フィードを表示するときは、条件に一致するユーザー ID のリストを DB から取得し、それらのユーザーによって投稿されたすべての NewsFeedPost を取得するだけです。早速、ダイナミック ニュース フィードです。

しかし、これは明らかに、その場で生成される NewsFeedPost テーブル全体のサブセットであるため、ユーザーが「もっと見る」をクリックするたびにこれを再計算するのは意味がありません。

テーブル - NewsFeedCurrent、NewsFeedRecent、NewsFeedArchive 新しい投稿は現在のテーブルに作成されます。毎晩バッチ ジョブが実行され、すべてのデータが 2 日前の現在のテーブルから最近のテーブルに移動され、最近のテーブル内の 1 週間前のすべてのデータがアーカイブ テーブルに移動されます。

90% の確率で、ユーザーは過去 2 日間のデータのみに関心があると考えられます。そのため、アクセス時間のためにテーブルを小さくしてください。さらに 9% の確率で、ユーザーは過去 1 週間のデータを必要とする場合があります。したがって、それをセカンダリテーブルで分離してください。次に、ユーザーが 1 週間以上前のデータを必要とするのは 1% の時間だけなので、それをより大きくて低速なアーカイブ テーブルに保持すると、速度は遅くなりますが、現在のテーブルと最近のテーブルを小さく保つことでパフォーマンスが向上します。

したがって、最初にニュース フィード ページにアクセスすると、アカウント用に事前に生成されたユーザー リストが取得され、NewsFeedCurrent のすべての項目が抽出されて一時的なテーブル (ユーザー ID の下の TempNewsFeed など) に配置されます。ユーザー ID のすべてを引き戻すだけで、この結果セットを操作できます。事前にフィルター処理されているため、興味のないアイテムをフィルター処理する必要はありません。これにより、ページの読み込みが 1 秒ほど長くなりますが、結果を取得する際の応答時間が改善されます。次に、そのデータが使い果たされると、再び条件に一致するユーザーのリストを使用して、最近のテーブルから関連するすべてのデータを引き出し、それを TempNewsFeed テーブルに追加して、1 週間前までのデータを取得し続けることができます。それが使い果たされると、最終的にアーカイブ テーブルに移動し、ユーザー ID リストを使用して、これに一致するすべてのデータを引き出して一時テーブルに配置すると、残りのデータのナビゲートを続行できます。これにより、アーカイブ データが読み込まれるため、かなりの遅延が発生しますが、1 週間前に戻る場合は、データが読み込まれ、「データを読み込んでいます...」と表示されるまで、5 ~ 10 秒待つ必要があります。ただし、履歴データのナビゲートは、すべてが一時テーブルにあるため、最近のデータと同じくらい迅速になります。

画面を更新するか、別の画面から画面に戻ると、一時テーブルがクリアされ、現在のテーブル データから再開されます。

4

1 に答える 1

0

私の答えが理にかなっていて、正しい仮定をしていることを願っています...

ニュース フィードを 2 つのセクションに分割します。1 つ目は着信ニュース用で、AJAX 呼び出しを使用します。常に「何が新しいの?」と言っています。2 番目のセクションは古いニュース用で、ユーザーは下にスクロールすることでより多くのニュースを遅延ロードできます。

最新のニュース項目

重要な点は、ページの最大ニュース フィード ID を書き留めておくことです。それが 10000 であると想像してみましょう。ユーザーがページを読み込んだとき、ニュース フィード ID 10000 が最新のニュース項目でした。

新しいセクションが AJAX で更新されると、単純に「id 10000 より新しいのは?」と尋ねます。それらのアイテムをページにロードします。それらをロードした後、ページの id もインクリメントします。たとえば、id 10000 から始めて 5 つの新しいニュース アイテムをロードした場合、新しい id は 10005 になります。次の呼び出しでは、「10005 より新しいのは何ですか?」と尋ねられます。

古いニュース項目

古いセクションは、ページの最も古いニュース項目を追跡します。彼らが 1 週間分のニュースをスクロールして戻ってくると想像してみましょう。最小のニュース アイテム ID は 9000 です。さらにスクロールして戻りたい場合は、単純に「9000 より古いものは何ですか?」と尋ねます。

アイデアは、ページ上で最大のニュース アイテム ID と最小のニュース アイテム ID を維持し、その参照ポイントから読み込みを続けることです。

于 2013-01-15T22:26:00.623 に答える