【发布时间】:2011-10-07 23:48:03
【问题描述】:
我正在尝试为在线商店构建一个穷人推荐系统。 我想实现这种亚马逊“购买此商品的客户也购买了”功能,我读了很多关于它的内容。 我知道有 Apache Mahout 的东西,但我无法以这种方式调整服务器。然后会有谷歌预测 API,但它要花钱,所以我开始自己试验。
我有一个包含 250.000 多个项目的订单历史记录,我编写了一个嵌套的 MySQL 查询来查找包含当前文章的订单,对其他订单项目进行排名并对该表进行排序以进行排名,所以我得到了一组其他人订购的产品连同当前的文章。
问题是,查询可能需要 10 秒 - 所以不能直接使用。 我想到了一个缓存表,但这个查询在 20 分钟后停止(有 60.000 个产品和 250.000 个已订购项目)所以我无法填写该表。
我目前的解决方法如下: 推荐 HTML 通过 AJAX ondocumentready 加载,因此网站加载,而推荐在后台加载。推荐数据被处理一次并存储在文件缓存(PEAR 简单缓存)中,因此下次加载速度更快。因此,如果有人访问该站点并存储一天或一周,则按需生成缓存。
我问我自己和你,这是一种可以接受的方法,还是愚蠢且表现不佳? 将缓存的数据存储在数据库或文件中会更好(我考虑性能和并行命中)。我的意思是,在最坏的情况下,我最终会得到 60.000 个缓存文件。
我更喜欢包含所有数据的预计算表,但正如我所说,这需要很长时间,而且我不知道如何优化它。 (等 SQL Dude 放假回来^^)
感谢任何提示,意见。
顺便说一句。这是查询:
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 是预计算的孩子订购当前项目的频率的计数。 现在,我可以在每个新订单上更新或插入相关项目,并计算排名(如果它已经存在于数据库中)。 我唯一担心的是,我最终会坐在一张非常大的桌子上。 如果我每周离线一次预先计算,也许这应该不是问题? 但随后我必须优化查询,以便每个项目不需要 10 秒。
你怎么看?
【问题讨论】:
标签: php mysql ajax recommendation-engine