【问题标题】:Mongodb query performance?MongoDB查询性能?
【发布时间】:2018-11-30 13:11:47
【问题描述】:

我有一个包含 360,000 个文档的 mongoDB 集合和一个包含 160,000 行的文本文件,其中 id 和文本由破折号分隔,如下格式:

 333-nice
 66446-bad
 88-good
 ...

我希望文本文件中破折号前的 id 与集合文档中的字段匹配时,更新或在新集合中创建文档。

我使用了以下查询,但它很慢,而且需要很长时间:

db.items_01.find().snapshot().forEach(function(elem)
{
  var products = cat("/Users/amirali/Desktop/kala.txt");
  var lines = products.split('\n');
  for(var i = 0;i < lines.length;i++)
  {
    var g_name = lines[i].split("-").pop();
    var pIg = g_name.replace("\"","");
    var pId = lines[i].substr(1, lines[i].indexOf('-')-1); 

    var field = elem.i_code;

    if(field.substring(0, 2) == pId)
    {
        db.items_additionals.update({
            "i_code": field
            },
            {
            $set: 
            {
                "i_code" : field,
                "class_id": field.substring(0, 2),
                "class": pIg
            }
        },{upsert:true});
    }

    if(field.substring(0, 3) == pId)
    {
        db.items_additionals.update({
            "i_code": field
            },
            {
            $set: 
            {
                "i_code" : field,
                "subclass_id": field.substring(0, 3),
                "subclass": pIg
            }
        },{upsert:true});
    }

    if(field.substring(0, 4) == pId)
    {
        db.items_additionals.update({
            "i_code": field
            },
            {
            $set: 
            {
                "i_code" : field,
                "group_id": field.substring(0, 4),
                "group": pIg
            }
        },{upsert:true});
    }

    if(field.substring(0, 5) == pId)
    {
        db.items_additionals.update({
            "i_code": field
            },
            {
            $set: 
            {
                "i_code" : field,
                "subgroup_id": field.substring(0, 5),
                "subgroup": pIg
            }
        },{upsert:true});
    }

    if(field.substring(0, 6) == pId)
    {
        db.items_additionals.update({
            "i_code": field
            },
            {
            $set: 
            {
                "i_code" : field,
                "category_id": field.substring(0, 6),
                "category": pIg
            }
        },{upsert:true});
    }

    if(field.substring(0, 7) == pId)
    {
        db.items_additionals.update({
            "i_code": field
            },
            {
            $set: 
            {
                "i_code" : field,
                "subcategory_id": field.substring(0, 7),
                "subcategory": pIg
            }
        },{upsert:true});
    }

  }
});

注意:文档中的 i_code 字段类似于8816370532410001

如何更改此查询以加快进度?

【问题讨论】:

    标签: javascript mongodb


    【解决方案1】:

    问题是您不使用集合的索引。相反,您线性遍历每个文档,然后对于每个文档,您线性遍历整个文件,因此整个运行需要 360000 乘以 160000 乘以单个文档到行操作的成本。

    我建议你在 outer 循环中浏览文件,然后查找正确的文档(如果 id 被索引,这会很快)。仅此一项就应该可以加快大约六个数量级。由于您也只会读取一次文件,因此它应该比这更快(磁盘操作很昂贵)。

    编辑:我现在看到您没有简单的索引查找。我猜是 你需要线性地经历这两个,但你应该收集的内容 首先将文件放入查找表中。我的意思是这样的 (未经测试):

    // read it only once
    var products = cat("~/foobar/kala.txt");
    var lines = products.split('n');
    
    // collect it into a map of id to words (I assume that there may be multiple
    // words for one id; if that is not the case, the arrays are not needed)
    
    var wordmap = {};
    
    lines.forEach( function (line) {
        var parts = line.split('-');
        id = parts[0].substr(1, parts[0].length - 1);
        word = parts[1].replace('"', '');
    
        if (!wordmap[id]) {
            wordmap[id] = [word];
        } else {
            wordmap[id].push(word);
        }
    } );
    
    // now go through the items, lookup the possible matching IDs in the map
    // created above
    
    db.items_01.find().snapshot().forEach( function (elem) {
        var i_code = elem.i_code;
        for (length = 2; length < 8; length++) {
            var id = i_code.substring(0, length);
            var words = wordmap[id];
            if (words) {
                words.forEach( function (word) {
                    db.items_additionals.update({"i_code": i_code},
                                                {$set: {"i_code": i_code,
                                                        "class_id": id,
                                                        "class": word}},
                                                {upsert: true});
                } );
            }
        }
    } );
    

    这应该会将复杂度从 360000 × 160000 降低到 360000 + 160000,而 避免读取文件 359999 次。

    【讨论】:

    • 你能给我一个例子,我怎样才能只读取一次文件和外循环?
    猜你喜欢
    • 1970-01-01
    • 2020-04-27
    • 2022-01-04
    • 1970-01-01
    • 2014-05-21
    • 2021-12-15
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多