5

オンライン ストアの貧乏人のレコメンデーション システムを構築しようとしています。そんなAmazonの「この商品を買った人は、こんな商品も買っている」機能を実現したくて、いろいろ読んでいます。Apache Mahout があることは知っていますが、そのようにサーバーを微調整することはできません。それからgoogleの予測APIもあるのですが、お金がかかるので自分で実験を始めています。

250.000 以上のアイテムを含む注文履歴を取得し、ネストされた MySQL クエリを作成して、現在の記事を含む注文を見つけ、他の注文アイテムをランク付けし、そのテーブルをランキング用に並べ替えました。現在の記事。

問題は、クエリに最大 10 秒かかる可能性があることです。そのため、これを直接使用することはできません。キャッシング テーブルを考えましたが、このクエリは 20 分後に停止します (60.000 個の製品と 250.000 個の注文アイテムがあります)。そのため、そのテーブルを埋めることができません。

私の現在の回避策は次のとおりです。レコメンデーション HTML は AJAX ondocumentready 経由で読み込まれるため、サイトは読み込まれますが、レコメンデーションはバックグラウンドで読み込まれます。推奨データは一度処理されてファイルキャッシュ (PEAR シンプルキャッシュ) に保存されるため、次回はより速く読み込まれます。したがって、誰かがサイトにアクセスすると、キャッシュはオンデマンドで作成され、1 日または 1 週間保存されます。

私は自分自身とあなたに尋ねます、それは受け入れられるアプローチですか、それとも愚かでパフォーマンスが悪いですか? キャッシュされたデータをデータベースまたはファイルに保存する方がよいでしょうか (パフォーマンスと並列ヒットについて考えます)。つまり、最悪の場合、60.000 個のキャッシュ ファイルが作成されることになります。

すべてのデータを含む事前計算されたテーブルが望ましいのですが、前述のとおり、時間がかかりすぎて最適化する方法がわかりません。(SQL 男が休暇から戻ってくるまで待っています ^^)

ヒント、意見をありがとう。

ところで。これはクエリです:

SELECT c.ArtNr as artnr , count(c.ArtNr) as rank, s.ArtNr as parent_artnr
FROM (
SELECT a.ID_order, a.ArtNr
        FROM net_orderposition a
        WHERE a.ArtNr = 'TT-PV0005'
) s
JOIN net_orderposition c 
WHERE s.ID_order = c.ID_order AND s.ArtNr != c.ArtNr
GROUP BY c.ArtNr
ORDER BY rank DESC,c.Stamp DESC
LIMIT 10;

編集:

与えられた答えについて考えてみましたが、最初の考えに似ていると思います。上記のコードの結果は、次の表になります。

ID,ParentID , ChildID  , Rank
1, TT-PV0005, TT-PV0040, 220
2, TT-PV0005, TT-PV0355, 135
3, TT-PV0005, TT-PV0450, 134
4, TT-PV0005, TT-PV0451, 89
5, TT-PV0005, RH-01V2  , 83
6, TT-PV0005, TT-PV0041, 83
7, TT-PV0005, TT-PV0353, 82
8, TT-PV0005, TT-PV0037, 80

ParentID は現在のアイテム、ChildID は ParentID とともに過去に注文したアイテム、Rank は現在のアイテムで子が注文された頻度の事前計算されたカウントです。これで、新しい注文ごとに関連アイテムを更新または挿入し、DB に既に存在する場合はランクをカウントできます。私が唯一恐れているのは、本当に大きなテーブルに座ることになることです。週に1回オフラインで事前計算すれば問題ないのではないでしょうか? ただし、クエリを最適化して、アイテムごとに 10 秒かからないようにする必要があります。

どう思いますか?

4

3 に答える 3

3

easyrecをチェックしてください。必要な機能があり、無料です。微調整は必要ありません、そしてあなたはグーグルアナリティクスのようにデモインスタンスを使うことができます。これを無料で使用してWebサービスを使用し、ロジック全体を自分でコーディングする方がはるかに簡単だと思います。

今日のツイートで、easyrecの完全なmahoutサポートをサポートしているため、easyrecですべてを利用できるとのことです。easyrecの無料のWebサービスを使用するか、無料のWARファイルをWebサーバーにデプロイできます。

于 2011-10-12T14:38:12.113 に答える
2

@GalacticCowboy の回答に追加して、コメントの場所を記入するには、@Marcus...

これを実現する 1 つのスキーマは、次のようなテーブルを作成することです。

RelatedItems
RelatedItemsId
purchasedItemId
relatedItemId

次に、注文が完了した (または要件に応じて表示された) ときに、RelatedItems テーブルにレコードを書き込みます。そこでは、購入した各アイテムが、その ID が purchaseItemId であるレコードを取得します。次に、他のすべての項目が relatedItemId として書き込まれます。

たとえば、アイテム 5、9、12、および 19 を購入した場合、次のような 12 のレコードがテーブルに書き込まれます。

RelatedItemId, PurchasedItemId, RelatedItemId
1, 5, 9
2, 5, 12
3, 5, 19
4, 9, 5
5, 9, 12
6, 9, 19
7, 12, 5
8, 12, 9
9, 12, 19
10, 19, 5
11, 19, 9
12, 19, 12

次に、GalacticCowboy と同様のクエリを使用して、それらの商品と一緒に通常購入された上位 10 の商品を取得できます。

これは、このようなタスクにとって最も効率的なスキーマではないことに注意してください。冗長なデータを減らすためにかなり微調整することができますが、システムと全体的なスキーマ設計 (およびいくつかの SQL の概念についての不安定な理解) 私はそれについて深く掘り下げるつもりはありません。

于 2011-07-18T20:28:42.923 に答える
0

注文があるたびに、注文内のさまざまなアイテム間の関係レコードを保存します。次に、次のようにします。

SELECT ItemID, COUNT(RelatedItemID) AS RelatedItemCount
FROM RelatedItems
WHERE RelatedItemID = @viewingItemID
GROUP BY ItemID
ORDER BY RelatedItemCount DESC
LIMIT 10

また、夜間のプロセスなどを使用してこれを事前に要約し、各アイテム IDの上位n件の関連アイテムのみを含むテーブルを作成することもできます。

于 2011-07-18T20:01:13.243 に答える