0

我在 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 毫秒。这种类型的查询是否可索引,如果可以,关于如何提高性能的任何想法?

4

2 回答 2

1

尝试删除以前的索引并使用多键标志创建,如下所示:

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

在我的测试用例中,我只有 100 个扫描对象和 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);
}

可能这对你来说是不正确的任务

于 2013-04-24T10:20:26.213 回答
0

我认为数据模型不太好。这是一个类似模型的关系。如果您可以像这样将数据模型更改为简单:

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

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

于 2013-04-24T10:53:03.027 回答