MongoDB嵌入式文档索引问题

时间:2013-04-22 22:46:08

标签: mongodb indexing mongodb-.net-driver mongodb-query

我在mongodb集合中有以下格式的数据:

{
    _id: ObjectId,
    Product: string,
    Modules: [
        {
            StaticModuleId: Int64,
            Set: [
                {
                    k: Int64,
                    v: {
                        Value: Double,
                        AnotherId: Int64


            }
            },
            ...
        ]
    }, 
    ...
]

}

这是我的名为MyIndex的索引:

{
    Product: 1,
    'Modules.StaticModuleId': 1,
    'Modules.Set.k': 1,
    'Modules.Set.v.Value': 1
}

该集合中有5个文档,每个文档中有10个模块和100个元素,总共50个模块和5000个条目。然后我运行了这个查询:

{
    'Product': 'Test',
    $and: [
        {
            'Modules.StaticModuleId': 2010220,
            'Modules.Set': {
                $elemMatch: {
                    k: 41439,
                    'v.Value': 2186233
                }
            }
        },
        {
            'Modules.StaticModuleId': 2010226
        },
        {
            'Modules.StaticModuleId': 2010228
        }
    ]
}

这是.explain():

{
    cursor: 'BtreeCursor MyIndex',
    isMultiKey: true,
    n: 4,
    nscannedObjects: 941,
    nscanned: 941,
    nscannedObjectsAllPlans: 941,
    nscannedAllPlans: 941,
    scanAndOrder: false,
    indexOnly: false,
    nYields: 0,
    nChunkSkips: 0,
    millis: 52  
}

当我继续添加额外的$ elemMatch子句时,性能会降低到> 200毫秒。这种类型的查询是否可转换,如果是,那么我是如何改进性能的?

2 个答案:

答案 0 :(得分:1)

尝试删除上一个索引并使用这样的多键标志创建:

db.collection.ensureIndex({{'Product':1, 'Modules.StaticModuleId':1, 'Modules.Set':1, 'Modules.Set.k':1, 'Modules.Set.v.Value':1}, {multikey:true})

在我的测试用例中,我只有100个scaned对象而millis = 0

提示:您可以通过以下方式将数据和/或索引加载到内存中:

db.runCommand({ touch: "collection", data: true, index: true })

我使用下一个脚本来重现问题和数据准备:

for(var prod=0; prod<1000; prod++) {
    prodObj={Product:"product" + prod};
    modObj=[];
    for(var mod=0; mod < 10; mod++) {
        seObj=[];
        for(var se=0; se < 100; se++) {
            seObj[se] = {k: "Int64-" + se, v:{Value:"Double-" + se}, AnotherId:"Int64"};
        }
        modObj[mod]={StaticModuleId:"Int64-"+prod, Set:seObj};
    }
    prodObj.Modules=modObj;
    db.so.insert(prodObj);
}

可能这对你的任务不正确

答案 1 :(得分:0)

我认为数据模型并不是那么好。这是一种类似模特的关系。如果您可以将数据模型更改为简单:

{
  Product: "string",
  StaticModuleId: "string",
  Set:
  [
    {
      k: "string",
      v: 
      {
        Value: "double",
        AnotherId: "string"
      }
    }
  ]
}

您将获得更好的性能和更低的复杂性