1

私たちの Ruby on Rails プロジェクトでは、調理方法、機会など、レシピの分類基準が多数あります。すべてのレシピは、これらのカテゴリの 1 つまたは複数に属しています。誰かがレシピの閲覧を開始すると、特定のカテゴリのセットに絞り込むことができます。次に、このセットからアクセスできるすべてのカテゴリのレシピの数を計算する必要があります (「アクセス可能」とは、選択したカテゴリにも属するそのカテゴリにレシピがあることを意味します)。これは、Amazon の検索の仕組みと似ています。誰かが「ソフトウェア」と入力すると、左側に「本 (200)」、「映画 (300)」などのメニューが表示されるので、ユーザーはこれらのリンクをクリックすることでさらに深く掘り下げることができます。

現在、大まかに次のように実装しています。

  1. URL から選択したカテゴリのセットを作成します。
  2. 現在選択されている基準に該当するすべてのレシピからカテゴリ ID を取得するクエリを実行します。
  3. すべてのカテゴリ ID をレシピのカウントにマップするインデックスを構築し、ゼロ以外のカウンターを持つものだけをレンダリングします。
  4. このインデックスは memcached に 24 時間保存されるため、特定のページについて 1 日に 1 回だけ計算されます。

私の懸念は、キャッシュ ミスがあると、インデックスの構築に時間がかかることです。この問題を解決する方法、または現在のソリューションを改善する方法について何か提案はありますか?

4

3 に答える 3

1

あなたが説明しているのは、本当に悪い組み合わせの問題です。選択したすべてのカテゴリについて、すべてのレシピを繰り返し、次にそのレシピのカテゴリを繰り返し、そのカテゴリのレシピ数を返します。最適化されたSQLを使用しても、ネストされたサブセレクトについて話しているため、論理的には指数関数的な時間未満でこれを行うことはできません. (つまり、大量のレシピを取得すると、これは非常に不利になります。) また、可能な組み合わせの数が (カテゴリ) ^ 2 になると、キャッシュもますます実用的ではなくなります。

このようにする必要がありますか?ところで、あなたは Amazon について間違っています。このような「クロスオーバー カテゴリ ビュー」はありません。これらは、検索ヒットの数を示します。これは、検索インデックスを使用すると簡単です。検索ボックスに「ソフトウェア」と入力しても、ソフトウェアをカテゴリとして扱っているわけではありません。それをキーワードとして扱っています。

誰もこの機能を要求していない場合は、単純化することをお勧めします。カテゴリ フィルター ビューで、一致するすべてのレシピを表示します。各レシピ ページで、そのレシピが含まれるすべてのカテゴリのサイドバー リストを表示できます。(これは、Categories モデルの属性として簡単にキャッシュでき、レシピを起動するときに熱心な読み込みで取得できます。)

なんらかの理由でこれを行う必要がある場合(Powers That Be は、ユーザーがフィルター処理を行わなかったカテゴリを本当に見たいと思っているという誤った印象の下でそれを要求します)、少なくとも SQL を使用してください。入れ子になった副選択は、データベースのメモリを食いつぶしますが、Ruby で行うよりも高速です。また、キャッシュの動作を変更する Rails プラグインもあります。これにより、現在のヒットで期限切れの結果が表示され、次のヒットでキャッシュが再生成されます。

しかし、より多くの作業を行う前に、クリックを追跡し、誰かがこれを使用しているかどうかを判断することを真剣にお勧めします.

于 2009-10-19T16:04:00.887 に答える
0

カテゴリ/製品の数に関する見積もりはありませんでしたが、たくさんあると思います:)

パフォーマンスが必要な場合、ここに私のアプローチがあります:(私は知っています、それはクレイジーです:))

  • カテゴリごとに、memcache にビット ベクトルを保持します。つまり、ID n の製品がそのカテゴリに属している場合、n 番目のビットは 1 です。

例を挙げましょう。製品 1、7、9、および 10 がカテゴリ A に属し、1、6、9 がカテゴリ B に属し、1、9、11 がカテゴリ C に属している場合、次のようになります。

  • A は 01000001 01100000 です
  • Bは01000010 01000000
  • C は 01000000 01010000 です

これらのセットの交差を計算したい場合は、セット間でビットごとの AND を作成するだけで、結果が得られます。

結果は次のとおりです。

  • 結果 = A と B と C = 01000000 01000000

カテゴリごとに計算したい場合は、別のカテゴリと結果を作成するだけです

備考:

  • DB 内の何かを変更する際にこれらのベクトルを再計算することを忘れないでください
  • 多くのカテゴリと交差することを計画している場合、これは非常に高速です
  • カテゴリごとに、TOTAL_NR_OF_PRODUCTS/8 より大きいベクトルを格納する必要があります
于 2009-07-26T20:32:12.573 に答える
0

毎日のインデックス作成はあまりきれいではありません。データセットを挿入または更新するときに、インデックスを付けませんか?

データセットを挿入する (レシピなど)

  • コンテンツをインデックスに追加するスレッドを開始します

  • スレッドでタイムアウト (1 秒など) が発生した場合 (高負荷!)、それを停止します。

毎日:

  • 現在のインデックスをディスクに保存します

  • インデックス全体を更新する

  • 失敗した場合は、保存されたインデックスをディスクから復元します

  • それ以外の場合は、インデックスを memcache に読み取ります

于 2009-07-26T20:13:36.653 に答える