Riak MapReduce:按字段分组项目+对另一个字段求和



无论我读到哪里,人们都说你不应该在整个bucket上使用Riak的MapReduce,还有其他方法可以实现你的目标。不过我不知道怎么做。我也不清楚为什么使用整个bucket很慢,如果整个系统中只有一个bucket,那么无论哪种方式,你都需要检查所有条目。

我有一个50多万份代表销售数据的文档列表。我需要以不同的方式查看这些数据:例如,业务运营的每个月有多少收入?每种产品的收入是多少?每个产品在一个月内售出了多少?我一直认为MapReduce应该擅长解决这些类型的聚合问题,所以我很困惑,如果你已经拥有了所有的密钥,MapReduce有什么用(你必须以某种方式搜索它们,对吧?(。

我的文档都在一个名为"sales"的bucket中,它们是具有以下字段的记录:{"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;

(现在订购不重要(。

你是对的,任何KV存储中的MapReduce都不会让它表现得像SQL数据库。有几件事可能对您的用例有所帮助。使用多个铲斗。您可以按产品、地区或月份对其进行细分,而不仅仅是一个Sales bucket,这样数据就已经按一个常见的报告标准进行了划分。考虑为每个字段的每个文档添加一个辅助索引。然后,您的月份查询可以是created_at索引的范围查询。如果你的id字段按顺序增加,并且你需要提取每月的数据,那么将每个月的开始和结束id存储在一个单独的键中(我知道,一旦写入数据,就不容易做到(。您还可以考虑将每个文档分解为一系列密钥。与其只将id键与值的json文档一起存储,不如为每个字段存储一个键,如id productid、id createdat、id price。这将最大限度地减少必须从磁盘读取并存储在RAM中才能处理MapReduce的数据量。

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

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

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

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

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

最新更新