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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM