我正在尝试为在线商店建立一个穷人的推荐系统。我想实现这种亚马逊“购买此商品的客户也购买了”功能,我读了很多关于它的内容。我知道有 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 秒。
你怎么看?