MongoDB 的 Map-Reduce

本文将介绍 MongoDB 的 Map-Reduce

Map-Reduce 是一种数据处理模式,用于将大量数据浓缩成有用的聚合结果。对于 Map-Reduce 操作,MongoDB 提供 mapReduce 数据库命令。考虑下面的 map-reduce 操作:

MongoDB 的 Map-Reduce

MongoDB 的 Map-Reduce

在这个 map-reduce 操作中,mongodb 将映射阶段应用于每个输入文档(即集合中与查询条件匹配的文档)。map 函数发出键值对。对于那些具有多个值的键,MongoDB 应用了 reduce 阶段,该阶段收集并压缩聚合的数据。然后 MongoDB 将结果存储在集合中。可选地,reduce 函数的输出可以通过 finalize 函数进一步浓缩或处理聚合的结果。

MongoDB 中的所有 map-reduce 函数都是 JavaScript,并在 mongod 进程中运行。map-reduce 操作,将单个集合的文档作为输入,在开始 map 阶段之前可以执行任意排序和限制。mapReduce 可以将 map-reduce 操作的结果作为文档返回,也可以将结果写入集合。

注意:对于大多数聚合操作,聚合管道提供更好的性能和更一致的接口。但是,map-reduce操作提供了一些灵活性,这在聚合管道中目前还没有。

Map-Reduce JavaScript 函数

在 MongoDB 中,map-reduce 操作使用自定义 JavaScript 函数将值映射或关联到键。如果一个键有多个映射到它的值,则 reduces 操作将键的值减少到单个对象。

自定义 JavaScript 函数的使用为 map-reduce 操作提供了灵活性。例如,在处理文档时,map函数可以创建多个键和值映射,或者不创建映射。map-reduce 操作还可以使用一个定制的 JavaScript 函数对map 和 reduce操作的结果进行最后的修改,比如执行额外的计算。

从4.2.1版开始,MongoDB反对在 map、reduce 和 finalize 函数中使用带有作用域(即BSON类型15)的JavaScript。要确定变量的作用域,请使用作用域参数。

Map-Reduce 结果

在 MongoDB 中,map-reduce 操作可以将结果写入集合或内联返回结果。如果将 map-reduce 输出写入集合,则可以在合并替换、合并或将新结果与先前结果合并的相同输入集合上执行后续的 map-reduce操作。

当以内联方式返回 map-reduce 操作的结果时,结果文档必须在 BSON 文档大小限制之内,目前这个限制是16兆字节。

Map-Reduce 和分片集合

MongoDB 支持对分片集合进行 map-reduce 操作,无论分片集合是作为输入(IN)还是作为输出(OUT)。

但是,从4.2版开始,MongoDB 就不支持使用 map-reduce 选项来创建新的分片集合,也不支持 map-reduce 使用 sharded 选项。若要输出到分片集合,首先需要创建该分片集合。MongoDB4.2 也不赞成替换现有的分片集合。

分片集合作为输入

当使用分片集合作为 map-reduce 操作的输入时,mongos 将自动并行地将 map-reduce 作业分派给每个分片,不需要特殊选项,mongos 将等待所有碎片上的工作完成。

分片集合作为输出

如果 mapReduce 的 out 字段有 sharded 值,MongoDB 使用 _id 字段作为分片键对输出集合进行分片。若要输出到分片集合,请执行以下操作:

  • 如果输出集合不存在,请首先创建分片集合。

    • 从4.2版开始,MongoDB 不支持使用 map-reduce 选项来创建新的分片集合,也不支持 map-reduce 使用 sharded 选项。因此,要输出到分片集合,首先需要创建分片集合。

    • 如果您没有首先创建切片集合,MongoDB 将在 _id 字段上创建切片集合。但是,建议您首先创建切分集合。

  • 从4.2版开始,MongoDB不赞成替换现有的分片集合。

  • 从4.0版开始,如果输出集合已经存在但不是分片集合,则 map-reduce 失败。

  • 对于新的或空的分片集合,MongoDB 使用 map-reduce 操作第一阶段的结果去创建分布在分片之间的初始化块。

  • mongos 并行地将一个 map-reduce 的后续处理作业分派给每个拥有块的分片。在后期处理期间,每个分片将从其他分片中为自己的块提取结果,运行最后的 reduce/finalize,并在本地将结果写入输出集合。

注意:

  • 在后来的 map-reduce 作业中,MongoDB 根据需要分割块。

  • 为了避免并发性问题,在后处理期间会自动阻止输出集合的块的平衡。

Map-Reduce 并发性

map-reduce 操作由许多任务组成,包括对输入集合的读取、map 函数的执行、reduce 函数的执行、在处理期间对临时集合的写入以及对输出集合的写入。在操作过程中,map-reduce 获取以下锁:

  • 读取阶段采用读锁。它每产生100份文件。

  • 临时集合中的插入对单个写操作使用写锁。

  • 如果输出集合不存在,则输出集合的创建将使用写锁。

  • 如果输出集合存在,则输出操作(即合并、替换、减少)采取写锁。这个写锁是全局的,并阻塞mongod实例上的所有操作。

注意

后处理期间的最终写锁使结果自动显示。但是,merge 和 reduce 输出操作可能需要几分钟的时间。对于 merge 和 reduce,nonAtomic 标记是可用的,它在写入每个输出文档之间释放锁。从 MongoDB 4.2 开始,显式地设置 nonAtomic:false 是不赞成的。

活着就要学习,学习不是为了活着。 —— 培根
0 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号