gpt4 book ai didi

performance - MongoDB 在使用 $all 和 $elemMatch 时扫描整个索引

转载 作者:行者123 更新时间:2023-12-02 00:52:18 28 4
gpt4 key购买 nike

我有一个用户文档集合,其中每个用户可以拥有任意一组属性。每个用户都与一个应用程序文档相关联。这是一个示例用户:

{
"appId": "XXXXXXX",
"properties": [
{ "name": "age", "value": 30 },
{ "name": "gender", "value": "female" },
{ "name": "alive", "value": true }
]
}

我希望能够根据用户的属性值查找/计数用户。例如,为我查找应用 X 的属性 Y > 10 且 Z 等于 true 的所有用户。

我在此集合上有一个复合多键索引 db.users.ensureIndex({ "appId": 1, "properties.name": 1, "properties.value": 1}) 。该索引对于单一条件查询效果很好,例如:

db.users.find({
appId: 'XXXXXX',
properties: {
$elemMatch: {
name: 'age',
value: {
$gt: 10
}
}
}
})

上述查询在 300 毫秒内完成,包含 100 万用户。但是,当我尝试添加第二个条件时,性能会显着下降(7-8 秒),并且 explain() 输出表明正在扫描整个索引来完成查询 ( “nscanned”:2752228)。

查询

db.users.find({
appId: 'XXXXXX',
properties: {
$all: [
{
$elemMatch: {
name: 'age',
value: {
$gt: 10
}
}
},
{
$elemMatch: {
name: 'alive',
value: true
}
}
]
}
})

解释一下

{
"cursor" : "BtreeCursor appId_1_properties.name_1_properties.value_1",
"isMultiKey" : true,
"n" : 256,
"nscannedObjects" : 1000000,
"nscanned" : 2752228,
"nscannedObjectsAllPlans" : 1018802,
"nscannedAllPlans" : 2771030,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 21648,
"nChunkSkips" : 0,
"millis" : 7425,
"indexBounds" : {
"appId" : [
[
"XXXXX",
"XXXXX"
]
],
"properties.name" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"properties.value" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"filterSet" : false
}

我认为这是因为 Mongo 无法创建合适的边界,因为我正在寻找 bool 值和整数值。

我的问题是:是否有更好的方法来构建我的数据,或者修改我的查询以提高性能并更好地利用我的索引?是否可以指示 mongo 分别处理每个条件,生成适当的边界,然后执行结果的交集,而不是扫描所有文档?或者 mongo 不适合这种类型的用例?

最佳答案

我知道这是一个老问题,但我认为在没有“名称”和“值”标签的情况下构建数据会更好:

{
"appId": "XXXXXXX",
"properties": [
{ "age": 30 },
{ "gender: "female" },
{ "alive": true }
]
}

关于performance - MongoDB 在使用 $all 和 $elemMatch 时扫描整个索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28610536/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com