オンライン ストアの貧乏人のレコメンデーション システムを構築しようとしています。そんな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 秒かからないようにする必要があります。
どう思いますか?