Mongodb Update操作需要很长时间才能在现有的集合文档中插入新的数组

时间:2015-10-05 10:30:01

标签: arrays mongodb mongodb-query

我的藏品中有大约250万份文件。现在我要在集合中的所有记录中添加两个数组字段。但是我的更新操作需要很长时间才能完成。以下是我的查询

db.products.update({
  "code": {
            "$nin": [
              "Tvs",
              "Lg",
              "Roots",
              "Mix",
              "A10",
              "PTPL",
              "Philips",
              "FireFox",
              "Akkade" ]
          }
         },
{
  "$push": {
    "rights": "Read",
    "Acc": "K23424"
  }
},
false,
true)

以上更新大约需要2分钟来更新整个集合。还有其他方法可以优化此更新查询。

修改

包括模型说明计划结果

{
    "cursor" : "BtreeCursor code_1",
    "isMultiKey" : false,
    "n" : 106192,
    "nscannedObjects" : 106192,
    "nscanned" : 106197,
    "nscannedObjectsAllPlans" : 106192,
    "nscannedAllPlans" : 106197,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 829,
    "nChunkSkips" : 0,
    "millis" : 275,
    "indexBounds" : {
        "code" : [ 
            [ 
                {
                    "$minElement" : 1
                }, 
                "adfgfgg"
            ], 
            [ 
                "5def354", 
                "akargfdc"
            ], 
            [ 
                "34aka545dc", 
                "akags"
            ], 
            [ 
                "354erak53ag345s", 
                "ci45t45r6rg"
            ], 
            [ 
                "cyuikitryui7ixsg", 
                "gp"
            ], 
            [ 
                "gp", 
                "gslbansgrp"
            ], 
            [ 
                "gsl7878nsgrp", 
                "l7hrgyn"
            ], 
            [ 
                "l678uhn", 
                "l6yup"
            ], 
            [ 
                "lfghrhyhp", 
                "radwaregslbsg"
            ], 
            [ 
                "radwaregslbsg", 
                "radwaregslbsgrs"
            ], 
            [ 
                "radwaregslbsgrs", 
                "radwarers"
            ], 
            [ 
                "rargydwarers", 
                "radwaresg"
            ], 
            [ 
                "radwargyresg", 
                "radwaresgrs"
            ], 
            [ 
                "radwaresgrs", 
                "slr6y6bsf"
            ], 
            [ 
                "slbrtrtsf", 
                {
                    "$maxElement" : 1
                }
            ]
        ]
    },
    "server" : "localhost:6789",
    "filterSet" : false,
    "stats" : {
        "type" : "FETCH",
        "works" : 106198,
        "yields" : 829,
        "unyields" : 829,
        "invalidates" : 0,
        "advanced" : 106192,
        "needTime" : 5,
        "needFetch" : 0,
        "isEOF" : 1,
        "alreadyHasObj" : 0,
        "forcedFetches" : 0,
        "matchTested" : 0,
        "children" : [ 
            {
                "type" : "IXSCAN",
                "works" : 106197,
                "yields" : 829,
                "unyields" : 829,
                "invalidates" : 0,
                "advanced" : 106192,
                "needTime" : 5,
                "needFetch" : 0,
                "isEOF" : 1,
                "keyPattern" : "{ code: 1.0 }",
                "isMultiKey" : 0,
                "boundsVerbose" : "field #0['code']: [MinKey, \"arhtgh10sg\"), (\"a1rgtrg0sg\", \"akadc\"), (\"akadc\", \"akags\"), (\"akags\", \"ctryitrrgyrtgyixsg\"), (\"crtytryityyrixsg\", \"gp\"), (\"gp\", \"gslytyybansgrp\"), (\"gstrytylbansgrp\", \"ln\"), (\"lrytryyn\", \"lyty5typ\"), (\"lty5ty5tp\", \"radwaregtryslbsg\"), (\"radwaregs454t45rgtlbsg\", \"radwaregslbsgrs\"), (\"radwa45654t6regslbsgrs\", \"radware46rs\"), (\"radwrfgarers\", \"rad456waresg\"), (\"r457423adwaresg\", \"radw34aresgrs\"), (\"ra5656dw5rty5aresgrs\", \"slbs6565656f\"), (\"slb66rty5rty5sf\", MaxKey]",
                "yieldMovedCursor" : 0,
                "dupsTested" : 0,
                "dupsDropped" : 0,
                "seenInvalidated" : 0,
                "matchTested" : 0,
                "keysExamined" : 106197,
                "children" : []
            }
        ]
    }
}

此致 根

1 个答案:

答案 0 :(得分:1)

问题在于,不等式运算符 $nin 不是很有选择性,因为它经常与索引的很大一部分匹配。因此,在许多情况下,带索引的 $nin 查询的效果可能不会超过必须扫描所有文档的 $nin 查询一个集合。想一想,索引对于找到匹配的东西非常有用,而不是找不到的东西。例如, $nin 查询返回集合中的每个文档但只返回一个文档,查询首先必须查看索引,然后返回文档。这是两个“查找”,而不是表格 扫描,只会查看每个文档一次。通常,如果您的查询需要使用超过一半的索引,则应重新检查查询的执行方式,或者至少采用表扫描。因此,如果您需要使用 $nin ,通常最好确保其他更具选择性的标准是查询的一部分。另请参阅Query Selectivity

您可以使用 Bulk API 作为优化更新的方法,包括确保选择性的其他查询,在这种情况下 Bulk.find().update() 查询包含 _id 字段,该字段默认为索引,并且唯一 _id 字段的相等匹配具有高度选择性,因为它可以匹配大多数文件。提高更新速度的另一个关键是要注意MongoDB如何控制服务器如何确认数据库操作。

以下示例初始化产品集合的 Bulk() 操作构建器,并将多个更新操作添加到操作列表中。它使用有序批量操作,按顺序逐步执行(因此名称),在出现错误时停止:

var bulk = db.products.initializeOrderedBulkOp(),
    counter = 0,
    criteria = {
        "code": {
            "$nin": [
              "Tvs",
              "Lg",
              "Roots",
              "Mix",
              "A10",
              "PTPL",
              "Philips",
              "FireFox",
              "Akkade" 
            ]
        }
    };

db.products.find().forEach(function(doc){

    bulk.find({ "_id": doc._id, "code": criteria.code }).update({
        "$push": { "rights": "Read", "Acc": "K23424" }
    })}

    counter++;
    if (counter % 1000 == 0) {
        // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk.execute();
        bulk = db.collection.initializeOrderedBulkOp();
    }
})

// Clean up queues
if (counter % 1000 != 0){
    bulk.execute();
}