(16)mongodb mapReduce分布式统计示例遇到的一个未解问题,求平均值不对,希望哪位大神给指点一下

  mapReduce 的优势在于分布式,这一节记录一个分布式统计的示例,整个过程分为这几步:启动分布式服务、手动分片、导入数据、执行 mapReduce。下面单独说说这几步。

1、启动分布式服务

  参考前面的第10节和第11节,不在重复说了。

2、手动分片:

  sh.enableSharding(‘test‘);  用test库做分片

  sh.shardCollection(‘test.dz‘,{sn:1});  指定片键,test库的dz集合,sn为片键

  mongos> for(var i=1;i<=8;i++){
  ... sh.splitAt(‘test.dz‘,{sn:i*1000});
  ... }                手动分片,当sn的值遇到1k、2k、3k...时形成一个chunk块

3、导数据,共7052条

  ./bin/mongoimport --port 30000  -d test -c dz --type csv -f sn,date,lev,wei,jing,deep,area --headerline --file ./地震数据.csv

  登录27017查看,导入了3053条  

  > db.dz.find().count();
  3053

  登录27018查看,导入了3999条

  > db.dz.find().count();
  3999

4、统计地址数据的分布,经纬度都是每跨5度统计在一起。

  var map = function(){

    var j = Math.floor(this.jing / 5) * 5;
    var w = Math.floor(this.wei / 5) * 5;
    var block =j + ‘:‘ + w;
    emit(block,1);
  }

  var reduce = function(block,values){
    return Array.sum(values);
  }

  db.dz.mapReduce(map,reduce,{out:‘res‘});

  分析:Math.floor()函数是取整数部分 ,计算出的 j 应该是每隔 5 度为单位,例如:5、10、15、20 等,计算出 j 等于 15,经度应该坐落在区间 [15,20)内。纬度同理可以 这样得到。看一下结果:

mongos> db.res.find();
{ "_id" : "-100:15", "value" : 9 }
{ "_id" : "-105:-40", "value" : 1 }
{ "_id" : "-105:10", "value" : 1 }
{ "_id" : "-105:15", "value" : 6 }
{ "_id" : "-105:5", "value" : 1 }
{ "_id" : "-10:-25", "value" : 1 }
{ "_id" : "-110:15", "value" : 4 }
{ "_id" : "-110:20", "value" : 1 }
{ "_id" : "-110:25", "value" : 1 }
{ "_id" : "-115:-30", "value" : 1 }
{ "_id" : "-115:-35", "value" : 2 }
{ "_id" : "-115:20", "value" : 1 }
{ "_id" : "-115:25", "value" : 4 }
{ "_id" : "-120:30", "value" : 1 }
{ "_id" : "-120:35", "value" : 3 }
{ "_id" : "-125:-60", "value" : 1 }
{ "_id" : "-125:35", "value" : 1 }
{ "_id" : "-125:40", "value" : 2 }
{ "_id" : "-130:40", "value" : 2 }
{ "_id" : "-130:45", "value" : 4 }
Type "it" for more
mongos> it
{ "_id" : "-135:50", "value" : 8 }
{ "_id" : "-135:55", "value" : 2 }
{ "_id" : "-140:55", "value" : 3 }
{ "_id" : "-145:55", "value" : 1 }
{ "_id" : "-145:60", "value" : 1 }
{ "_id" : "-150:55", "value" : 1 }
{ "_id" : "-150:65", "value" : 1 }
{ "_id" : "-155:55", "value" : 6 }
{ "_id" : "-155:60", "value" : 2 }
{ "_id" : "-15:-20", "value" : 1 }
{ "_id" : "-15:-5", "value" : 1 }
{ "_id" : "-15:-60", "value" : 1 }
{ "_id" : "-15:70", "value" : 2 }
{ "_id" : "-160:15", "value" : 1 }
{ "_id" : "-160:55", "value" : 2 }
{ "_id" : "-160:65", "value" : 1 }
{ "_id" : "-165:50", "value" : 2 }
{ "_id" : "-170:50", "value" : 5 }
{ "_id" : "-175:-20", "value" : 16 }
{ "_id" : "-175:-25", "value" : 13 }
Type "it" for more
mongos> it
{ "_id" : "-175:50", "value" : 10 }
{ "_id" : "-180:-15", "value" : 2 }
{ "_id" : "-180:-20", "value" : 26 }
{ "_id" : "-180:-25", "value" : 23 }
{ "_id" : "-180:-30", "value" : 7 }
{ "_id" : "-180:-35", "value" : 22 }
{ "_id" : "-180:50", "value" : 9 }
{ "_id" : "-20:-40", "value" : 1 }
{ "_id" : "-20:-45", "value" : 1 }
{ "_id" : "-20:-5", "value" : 1 }
{ "_id" : "-20:-60", "value" : 1 }
{ "_id" : "-20:-65", "value" : 1 }
{ "_id" : "-25:-5", "value" : 1 }
{ "_id" : "-25:-60", "value" : 3 }
{ "_id" : "-30:-60", "value" : 15 }
{ "_id" : "-30:-65", "value" : 1 }
{ "_id" : "-35:-60", "value" : 1 }
{ "_id" : "-35:50", "value" : 1 }
{ "_id" : "-35:55", "value" : 2 }
{ "_id" : "-45:10", "value" : 1 }
Type "it" for more

  为了验证数据的正确性,可以将数据导入mysql中,以下面这三条数据为例子说明 mapReduce 的统计是正确的

  { "_id" : "-100:15", "value" : 9 }  select * from dzsj w WHERE  w.jing>=-100 and w.jing<-95 and w.wei>=15 and w.wei<20

  { "_id" : "-115:25", "value" : 4 }  select * from dzsj w WHERE w.jing>=-115 and w.jing<-110 and w.wei>=25 and w.wei<30

  { "_id" : "-155:55", "value" : 6 }  select * from dzsj w WHERE w.jing>=-155 and w.jing<-150 and w.wei>=55 and w.wei<60

5、在上面的基础上统计平均震级,这次只统计经纬度大于0的,这里出现了问题尚未解决。

  var map = function(){

    if(this.jing<0 || this.wei<0){
      return;
    }
    var j = Math.floor(this.jing / 5) * 5;
    var w = Math.floor(this.wei / 5) * 5;
    var block =j + ‘:‘ + w;
    emit(block,this.lev);
  }

  var reduce = function(block,values){
    return Array.avg(values);
  }

  db.dz.mapReduce(map,reduce,{out:‘res‘});

  执行结果如下:

mongos> db.res.find().sort({value:-1});
{ "_id" : "65:25", "value" : 7.5 }
{ "_id" : "140:65", "value" : 7.3 }
{ "_id" : "60:25", "value" : 7.050000000000001 }
{ "_id" : "95:50", "value" : 7 }
{ "_id" : "140:25", "value" : 6.920833333333333 }
{ "_id" : "150:50", "value" : 6.85 }
{ "_id" : "25:40", "value" : 6.8 }
{ "_id" : "95:5", "value" : 6.8 }
{ "_id" : "125:10", "value" : 6.783333333333333 }
{ "_id" : "165:50", "value" : 6.733333333333333 }
{ "_id" : "90:20", "value" : 6.666666666666667 }
{ "_id" : "160:50", "value" : 6.645 }
{ "_id" : "175:50", "value" : 6.608333333333333 }
{ "_id" : "125:30", "value" : 6.6 }
{ "_id" : "145:0", "value" : 6.6 }
{ "_id" : "90:0", "value" : 6.5166666666666675 }
{ "_id" : "155:50", "value" : 6.4875 }
{ "_id" : "45:30", "value" : 6.47 }
{ "_id" : "140:10", "value" : 6.45 }
{ "_id" : "135:30", "value" : 6.445833333333333 }
Type "it" for more
mongos> it
{ "_id" : "140:15", "value" : 6.4 }
{ "_id" : "145:15", "value" : 6.4 }
{ "_id" : "145:5", "value" : 6.4 }
{ "_id" : "135:35", "value" : 6.35 }
{ "_id" : "140:20", "value" : 6.300000000000001 }
{ "_id" : "95:15", "value" : 6.300000000000001 }
{ "_id" : "165:55", "value" : 6.3 }
{ "_id" : "160:55", "value" : 6.254166666666666 }
{ "_id" : "140:40", "value" : 6.239583333333333 }
{ "_id" : "125:5", "value" : 6.222916666666666 }
{ "_id" : "125:0", "value" : 6.217499999999999 }
{ "_id" : "5:70", "value" : 6.2 }
{ "_id" : "65:40", "value" : 6.2 }
{ "_id" : "155:45", "value" : 6.1899999999999995 }
{ "_id" : "120:10", "value" : 6.185714285714285 }
{ "_id" : "145:45", "value" : 6.175000000000001 }
{ "_id" : "170:50", "value" : 6.166666666666666 }
{ "_id" : "25:35", "value" : 6.154166666666667 }
{ "_id" : "120:0", "value" : 6.15 }
{ "_id" : "135:25", "value" : 6.15 }
Type "it" for more
mongos> 

拿出两个数据来对比,发现并不是我们要的结果:

  { "_id" : "140:20", "value" : 6.300000000000001}  

  select AVG(lev) from dzsj w WHERE  w.jing>=140 and w.jing<145 and w.wei>=20 and w.wei<25  计算结果是 6.333333333333333

  { "_id" : "145:45", "value" : 6.175000000000001 }

  select * from dzsj w WHERE  w.jing>=145 and w.jing<150 and w.wei>=45 and w.wei<50  计算结果是 6.08

  { "_id" : "160:55", "value" : 6.114285714285715 }

  select AVG(lev) from dzsj w WHERE  w.jing>=160 and w.jing<165 and w.wei>=55 and w.wei<60  计算结果是 6.050000000000001

我们先求一下和,执行以下代码:

var map = function(){
  if(this.jing<0 || this.wei<0){
     return;
  }
  var j = Math.floor(this.jing / 5) * 5;
  var w = Math.floor(this.wei / 5) * 5;
  var block =j + ‘:‘ + w;
  emit(block,this.lev);
}

var map = function(){
  var j = Math.floor(this.jing / 5) * 5;
  var w = Math.floor(this.wei / 5) * 5;
  var block =j + ‘:‘ + w;
  emit(block,this.lev);
}

var reduce = function(block,values){
  return Array.sum(values);
}

db.dz.mapReduce(map,reduce,{out:‘res‘});

查看一下部分结果:

mongos> db.res.find({_id:‘140:20‘});
{ "_id" : "140:20", "value" : 19 }
mongos> db.res.find({_id:‘145:45‘});
{ "_id" : "145:45", "value" : 30.400000000000002 }
mongos> db.res.find({_id:‘160:55‘});
{ "_id" : "160:55", "value" : 48.400000000000006 }
mongos> 

与mysql中对比一下,发现求和是一样的。

  select SUM(lev) from dzsj w WHERE w.jing>=140 and w.jing<145 and w.wei>=20 and w.wei<25  19

  select SUM(lev) from dzsj w WHERE  w.jing>=145 and w.jing<150 and w.wei>=45 and w.wei<50  30.400000000000002

  select SUM(lev) from dzsj w WHERE  w.jing>=160 and w.jing<165 and w.wei>=55 and w.wei<60  48.400000000000006

在对比一下前面求的数量,发现数量也是一样的。

  { "_id" : "140:20", "value" : 3 }
  { "_id" : "145:45", "value" : 5 }
  { "_id" : "160:55", "value" : 8 }

  select count(1) from dzsj w WHERE w.jing>=140 and w.jing<145 and w.wei>=20 and w.wei<25  3
  select count(1) from dzsj w WHERE w.jing>=145 and w.jing<150 and w.wei>=45 and w.wei<50  5
  select count(1) from dzsj w WHERE w.jing>=160 and w.jing<165 and w.wei>=55 and w.wei<60  8

这就奇怪了,求和一样,求数量也一样,计算出的平均值不一样,哪位好心人能发现问题希望能指点一二,谢谢!

  

  

原文地址:https://www.cnblogs.com/javasl/p/11336712.html

时间: 2024-11-08 10:05:21

(16)mongodb mapReduce分布式统计示例遇到的一个未解问题,求平均值不对,希望哪位大神给指点一下的相关文章

大神必修课系列之java 分布式架构的原理解

分布式术语 1.1. 异常 服务器宕机 内存错误.服务器停电等都会导致服务器宕机,此时节点无法正常工作,称为不可用. 服务器宕机会导致节点失去所有内存信息,因此需要将内存信息保存到持久化介质上. 网络异常 有一种特殊的网络异常称为--网络分区 ,即集群的所有节点被划分为多个区域,每个区域内部可以通信,但是区域之间无法通信. 磁盘故障 磁盘故障是一种发生概率很高的异常. 使用冗余机制,将数据存储到多台服务器. 1.2. 超时 在分布式系统中,一个请求除了成功和失败两种状态,还存在着超时状态. 可以

大神必修课系列之java 分布式架构的原理解析

分布式术语 1.1. 异常 服务器宕机 内存错误.服务器停电等都会导致服务器宕机,此时节点无法正常工作,称为不可用. 服务器宕机会导致节点失去所有内存信息,因此需要将内存信息保存到持久化介质上. 网络异常 有一种特殊的网络异常称为--网络分区 ,即集群的所有节点被划分为多个区域,每个区域内部可以通信,但是区域之间无法通信. 磁盘故障 磁盘故障是一种发生概率很高的异常. 使用冗余机制,将数据存储到多台服务器. 1.2. 超时 在分布式系统中,一个请求除了成功和失败两种状态,还存在着超时状态. 可以

mongodb mapreduce使用总结

文章来自本人个人博客: mongodb mapreduce使用总结 ? 大家都知道,mongodb是一个非关系型数据库,也就是说,mongodb数据库中的每张表是独立存在的,表与表之间没有任何依赖关系.在mongodb中,除了各种CRUD语句之外,还给我们提供了聚合和mapreduce统计的功能,这篇文章主要来跟大家聊聊mongodb的mapreduce的操作. ?mapreduce的概念我就不赘述了,大家自己去查查吧. ?在mongodb中,mapreduce的语法如下: ? db.table

MapReduce分布式编程模型

hdfs的副本的配置修改hdfs-site.xml文件<property><name>dfs.namenode.secondary.http-address</name><value>hd-02:50090</value></property>需要同步到其它机器:scp hdfs-site.xml hd-02:$PWDhadoop启动方式1)启动hdfs集群$ start-dfs.sh2)启动yarn集群$ start-yarn.sh

mongodb的分布式集群(1、主从复制)

分布式集群的理解 关于分布式集群的概念有很多的解释,我比较倾向于"分布式集群"为两个概念,即,分布式是一个概念,集群是另一概念. 分布式是把一个整体系统分成多个部分,分别部署到不同的服务器上,然后由中心服务器统一控制,形成的一个对外来说为一个整体的系统.集群是把一个整体,整体的分别部署到多个服务器上的结果. 分布式和集群都是部署上的现象的描述,都涉及到多台服务器的部署,这是分布式和集群相同的地方,当然,其达到的效果也有很多一样的,但是,他们却是描述着两种不同的现象.今天就讲一下关于mo

mongodb的分布式集群(3、分片)

概述 上面两篇博客都是关于mongodb的集群的配置,没有涉及到分布式,该片博客就是写mongodb的分布式,把一个整体,分成多个片,每个片部署到不同的服务器上,这个就是mongodb的分布式,即:mongodb的分片操作. 部署图 mongos服务器做的是路由服务器,config服务器就是保存相应配置的服务器,shard1和shard2就是分片服务器,这两个服务器合在一起才是一个整体,而mongos服务器就是他们的和点,所以,我们客户端只需要和mongos服务器交互就可以了,后面的,服务器自己

mongodb的分布式集群(4、分片和副本集的结合)

概述 前面3篇博客讲了mongodb的分布式和集群,其中第一种的主从复制我们几乎不用,没有什么意义,剩下的两种,我们不论单独的使用哪一个,都会出现相应的问题,比较好的一种解决方案就是,分片和副本集的集合使用,这样就比较完美了. 部署图 在这里,我们需要注意,我们mongos服务器配置成了集群,所以,我们需要在客户端上分别得添加相应的地址,这个和在副本集的那篇博客中将的内容一样,在java客户端程序的具体核心代码,在那篇博客中也给了大家,如果这点不清楚的,可以看看那篇博客. 分片集群的配置 分片集

浅尝key-value数据库(三)——MongoDB的分布式

浅尝key-value数据库(三)——MongoDB的分布式 测试了单机MongoDB的随机读和写入性能,这一节来讲一讲MongoDB的分布式. MongoDB的分布式分成两种,一种是Replication,一种是Sharding.我们主要来看一下Sharding. 先贴一张结构示意图: MongoDB Auto-Sharding的配置非常简单,在不同的机器分别开启shard, config server, mongos的进程即可.(假设config serevr的IP为192.168.1.11

7月目标 socket , 一致性哈希算法 ; mongodb分片; 分布式消息队列; 中间件的使用场景

  分布式的基础:一致性哈希  路由算法的一致性hash http://www.jiacheo.org/blog/174 http://www.tuicool.com/articles/vQVbmai http://www.cnblogs.com/huangxincheng/p/3708316.html   redis 和 mongodb的使用,要能自己写 helper帮助类,和多台机器上的使用   socket http://www.cnblogs.com/JimmyZhang/archive