Riak MapReduce:按字段分组项目+另外一个字段

时间:2013-04-14 09:38:41

标签: erlang riak

我读到的每个地方,人们都说你不应该在整个存储桶中使用Riak的MapReduce,并且还有其他方法可以实现你的目标。不过我不知道怎么回事。我还不清楚为什么使用整个存储桶的速度很慢,如果整个系统中只有一个存储桶,那么无论哪种方式,都需要查看所有条目。

我有一份代表销售数据的500K +文件清单。我需要以不同的方式查看这些数据:例如,企业运营的每个月收入是多少?每种产品的收入是多少?每个产品在一个月内销售了多少?我一直认为MapReduce应该善于解决这些类型的聚合问题,所以我很困惑如果你已经拥有了所有的密钥(你必须搜索它们,不管怎样,对吧?),使用MapReduce会是什么。 p>

我的文档全部位于名为“sales”的存储桶中,它们是包含以下字段的记录:{"id":1, "product_key": "cyber-pet-toy", "price": "10.00", "tax": "1.00", "created_at": 1365931758}

让我们举一个例子,我需要报告过去4年中每个月每个产品的总收入(基本上是整个桶),如何使用Riak的MapReduce来有效地做到这一点?即使只是尝试对数据使用身份映射操作,我在大约30秒后得到超时,MySQL以毫秒为单位处理。

我在Erlang中这样做(使用协议缓冲客户端),但任何语言都可以解释。

等效的SQL(MySQL)将是:

  SELECT SUM(price)                         AS revenue,
         FROM_UNIXTIME(created_at, '%Y-%m') AS month,
         product_key
    FROM sales
GROUP BY month, product_key
ORDER BY month ASC;

(现在订购不重要)。

2 个答案:

答案 0 :(得分:2)

你是对的,任何KV商店中的MapReduce都不会使它像SQL数据库一样。有几件事可能对您的用例有所帮助。使用多个桶。您可以按产品,区域或月份拆分它们,而不仅仅是销售桶,因此数据已经按照您的一个常见报告标准进行拆分。考虑为每个字段的每个文档添加二级索引。您的月份查询可以是created_at索引的范围查询。如果您的id字段按顺序递增并且您需要提取每月数据,请将每个月的开始和结束ID存储在一个单独的密钥中(一旦写入数据就不容易做,我知道)。您还可以考虑将每个文档分解为一系列键。不是仅存储带有json文档的id键作为值,而是存储每个字段的键,如id-productid,id-createdat,id-price。这将最大限度地减少必须从磁盘读取并存储在RAM中的数据量,以便处理MapReduce。

为了正确看待这个问题,请考虑以下(非常讽刺)假设:我在MySQL数据库中有500K文档,每个文档都包含一个json字符串。我的数据库由一个名为Sales的表组成,其中一个名为Data的列将我的文档存储为二进制blob。如何编写快速,高效的SQL语句,只选择包含日期的文档并按月分组?

我要说的是,您必须根据您选择使用的数据存储的优势来设计数据对象的结构。除非您使用类似solr的搜索,否则Riak在处理JSON方面效率不高,但可能有一些方法可以重构您可能能够处理的数据。或许这意味着另一个数据存储更适合您的需求。

答案 1 :(得分:1)

目前,我为需要经常搜索的文档属性创建二级索引,并使用这个小得多的键子集作为MapReduce作业的输入。

http://docs.basho.com/riak/latest/tutorials/Secondary-Indexes---Examples/

我同意与我使用的其他系统相比,运行像这样的大型MapReduce作业似乎非常昂贵。