我一直在用 CouchDB 玩 Map Reduce。一些示例在 map reduce 函数中显示了一些可能很繁重的逻辑。在一种特殊情况下,他们在 map 中执行 for 循环。
在发出您选择的文档之前,map reduce 是否在每个可能的文档上运行?
如果是这样,我认为这意味着在map reduce 函数中运行任何类型的迭代处理至少会增加一个数量级的处理负担。
基本上它归结为以下问题:在 map reduce 执行不合理昂贵的查询之前可以执行多少逻辑?
在 CouchDB map-reduce 中可以接受大量昂贵的处理。
CouchDB 视图(map-reduce)更像CREATE INDEX
是SELECT FROM
.
具体来说,CouchDB 保证 map 函数在每个文档中只运行一次。(嗯,实际上每个文档更改一次。)这就是“迭代映射减少”。
因此,假设您有 10,000 个文档,每个文档需要 1秒来处理(这比我见过的要高得多)。也就是说,完全构建视图需要 10,000 秒或 2.8 小时。但是,一旦视图完成,查询任何行 ( ?key=...
) 或行切片 ( ?startkey=...&endkey=...
) 与直接查询文档所花费的时间相同。文档计数的查找时间为 O(log n)。
换句话说,即使每个文档需要 1 秒来执行映射,也需要几毫秒来获取结果。(当然,视图必须先构建,因为它实际上是一个索引。)
查询数据库是与文档的 map/reduce 无关的活动。因此查询成本不受 map/reduce 复杂性的影响。
在 couchdb 中,您正在查询索引。这意味着它是以针对查询速度优化的格式复制您的数据。查询不像 sql 中的表扫描。它不会遍历记录。
那么如何制作这个索引呢?它是通过地图功能完成的。map 函数发出一个键和一个值。键放在索引中。您提到的一些复杂的映射函数可能会循环并发出许多键和值。Couchdb 很聪明,只在需要时运行文档,通常是在创建、更新和删除时。这就是为什么它是增量映射/减少。
如您所见,复杂的地图功能可能会影响创建、更新和删除速度。但是,couchdb 再次很聪明,因为您可以在查询索引时指定数据的陈旧程度。