zoukankan      html  css  js  c++  java
  • mongodb系列(一)mongoose find普通查询与aggregate聚合查询的 简单性能对比

    背景

    mongodb 3.4,使用默认的配置(没有调整内存限制或其他性能配置),数据库有90万+条数据

    开始实验

    以下分别使用 find 查询 和 aggregate 聚合查询

    以下为dao层(server/dao/cmsResourceDao.js),基于mongoose查询mongodb

    1.  
      getModel(){
    2.  
      return mongoose.model(this.model_name); //model_name 为collection名称
    3.  
      }
    4.  
       
    5.  
      /***
    6.  
      * 使用find 查询,并且是分页查询
    7.  
      * @param limit_param 条件
    8.  
      * @param page_index 数据页码起始下标
    9.  
      * @param page_size 数据每页数量
    10.  
      * @param sort 排序条件
    11.  
      * @returns {Promise.<{rows: *, total_count: *}>}
    12.  
      */
    13.  
      async listPage(limit_param,page_index,page_size,sort){
    14.  
      let rows;
    15.  
      if(sort != null){
    16.  
      rows = await this.getModel().where(limit_param).skip(Number(page_index)).limit(Number(page_size)).sort(sort).exec();
    17.  
      }else{
    18.  
      rows = await this.getModel().where(limit_param).skip(Number(page_index)).limit(Number(page_size)).exec();
    19.  
      }
    20.  
      return {rows};
    21.  
      }
    22.  
       
    23.  
      /***
    24.  
      * 使用aggregate聚合 查询,并且是分页查询
    25.  
      * @param limit_param 条件
    26.  
      * @param page_index 数据页码起始下标
    27.  
      * @param page_size 数据每页数量
    28.  
      * @param sort 排序条件
    29.  
      * @returns {Promise.<{rows: *, total_count: *}>}
    30.  
      */
    31.  
      async listAggregatePage(limit_param,page_index,page_size,sort){
    32.  
       
    33.  
      let aggregate_limit = [{$match:limit_param},
    34.  
      {$skip:Number(page_index)},
    35.  
      {$limit:Number(page_size)}];
    36.  
       
    37.  
      if(sort != null)aggregate_limit.push({$sort:sort});
    38.  
       
    39.  
      let rows = await this.getModel().aggregate(aggregate_limit);
    40.  
      return {rows};
    41.  
      }

    1.find查询和aggregate查询(不使用sort排序)

    以下为使用find查询50000条数据返回:

    1.  
      async list(ctx,next){
    2.  
       
    3.  
      console.log('list!!!');
    4.  
      let type = ctx.request.query.type;
    5.  
      let page_index = ctx.request.query.page_index;
    6.  
      let page_size = ctx.request.query.page_size;
    7.  
       
    8.  
      let where = {};
    9.  
      if(type != null)where.type = type;
    10.  
       
    11.  
      let start_time = new Date().getTime();
    12.  
      let result = await dao.listPage(where,page_index,page_size);
    13.  
      // let result = await dao.listAggregatePage(where,page_index,page_size); //使用聚合查询方式
    14.  
      let end_time = new Date().getTime();
    15.  
      console.log('查询时间:');
    16.  
      console.log(end_time - start_time);
    17.  
      ctx.body = {
    18.  
      data : result,
    19.  
      time : new Date().getTime() - start_time
    20.  
      }
    21.  
      }

    打印的时间是: 8504ms

     使用aggregate查询50000条数据返回:

    1.  
      async list(ctx,next){
    2.  
       
    3.  
      console.log('list!!!');
    4.  
      let type = ctx.request.query.type;
    5.  
      let page_index = ctx.request.query.page_index;
    6.  
      let page_size = ctx.request.query.page_size;
    7.  
       
    8.  
      let where = {};
    9.  
      if(type != null)where.type = type;
    10.  
       
    11.  
      let start_time = new Date().getTime();
    12.  
      // let result = await dao.listPage(where,page_index,page_size);
    13.  
      let result = await dao.listAggregatePage(where,page_index,page_size); //使用聚合查询方式
    14.  
      let end_time = new Date().getTime();
    15.  
      console.log('查询时间:');
    16.  
      console.log(end_time - start_time);
    17.  
      ctx.body = {
    18.  
      data : result,
    19.  
      time : new Date().getTime() - start_time
    20.  
      }
    21.  
      }

    打印的时间是: 2241ms

    2.find查询和aggregate查询(使用sort排序)

    使用sort排序挑战性能极限

    在刚才使用find查询,添加sort条件

    let result = await dao.listPage(where,page_index,page_size,{updated_at:-1});

    结果控制台报出,内存超出限制(最大值为 33554432 bytes 折合为 32mb左右 ):

    service error { MongoError: Executor error during find command: OperationFailed: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit.

    使用aggregate查询,添加sort条件

    let result = await dao.listAggregatePage(where,page_index,page_size,{updated_at:-1}); //使用聚合查询方式

    打印的时间是: 2298ms

    那么aggregate查询的内存最大值究竟有多少呢?再玩大的,这次查询10万条

    service error { MongoError: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation. Pass allowDiskUse:true to opt in.

    由此可见 aggregate对排序也是有内存限制的(最大值为104857600 bytes折合为100mb左右)

    总结

    从查询的速度看,aggregate效率更胜一筹。

    从内存限制看,aggregate比find更高一点。

    从上述实验中,aggregate 好像比 find 查询 更胜一筹,但并不意味着 aggregate就是最好的,初步判断这是由于aggregate更消耗内存换取查询的速度。下一集,再深层次挖掘两者区别

    PS: 源码已提交到github 

    https://github.com/rcjjian/big_data_lab

  • 相关阅读:
    JCL: What is EXCP
    百分比布局的使用
    使用TabLayout快速实现一个导航栏
    彻底理解android中的内部存储与外部存储
    Eclipse的LogCat总是自动清空怎么办?
    怎么给Unity写一个原生的插件
    一句话、一张图记住Activity和Fragment之间错综复杂的生命周期关系
    2015年工作中遇到的问题:131-140(有图才有真相)
    2015年工作中遇到的问题:131-140(有图才有真相)
    雷观(二十四):谈谈我对国家事务“二胎”和“教育”的一些看法
  • 原文地址:https://www.cnblogs.com/ExMan/p/13926979.html
Copyright © 2011-2022 走看看