0

在我读到的所有地方,人们都说您不应该在整个存储桶上使用 Riak 的 MapReduce,并且还有其他方法可以实现您的目标。不过,我不确定如何。我也不清楚为什么使用整个存储桶很慢,如果您在整个系统中只有一个存储桶,那么无论哪种方式,您都需要检查所有条目。

我有一个代表销售数据的 500K+ 文档的列表。我需要以不同的方式查看这些数据:例如,企业运营每个月的收入是多少?每个产品增加了多少收入?在给定的一个月内,每种产品销售了多少?我一直认为 MapReduce 应该擅长解决这些类型的聚合问题,所以如果您已经拥有所有键(您必须以某种方式搜索它们,对吗?),我很困惑 MapReduce 的用途。

我的文档都在一个名为“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;

(现在订购不重要)。

4

2 回答 2

2

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

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

我要说的是,您必须根据您选择使用的数据存储的优势来设计数据对象的结构。Riak 在处理 JSON 方面并不是特别有效,除非您使用他们的类似 solr 的搜索,但可能有一些方法可以重组您可能能够处理的数据。或者这可能意味着另一个数据存储会更好地满足您的需求。

于 2013-04-15T13:06:06.167 回答
1

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

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

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

于 2013-04-15T00:02:59.530 回答