我对一个大约有160万个寄存器的集合进行了汇总。那个咨询是一个简单的例子,其他比较复杂,但说明了我认为使用的索引优化不好。
db.getCollection('cbAlters').runCommand("aggregate", {pipeline: [
{
$match: { cre_carteraId: "31" }
},
{
$group: { _id: { ca_tramomora: "$cre_tramoMora" },
count: { $sum: 1 } }
}
]})
该查询花费了大约5秒。该集合有25个索引配置为不同的咨询。根据查询解释使用的是:
{
"v" : 1,
"key" : {
"cre_carteraId" : 1,
"cre_periodo" : 1,
"cre_tramoMora" : 1,
"cre_inactivo" : 1
},
"name" : "cartPerTramInact",
"ns" : "basedatos.cbAlters"
},
我为这个特定的查询创建了一个索引:
{
"v" : 1,
"key" : {
"cre_carteraId" : 1,
"cre_tramoMora" : 1
},
"name" : "cartPerTramTest",
"ns" : "basedatos.cbAlters"
}
查询优化器拒绝这个索引,并建议我使用初始索引。我的查询的输出解释如下:
{
"waitedMS" : NumberLong(0),
"stages" : [
{
"$cursor" : {
"query" : {
"cre_carteraId" : "31"
},
"fields" : {
"cre_tramoMora" : 1,
"_id" : 0
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "basedatos.cbAlters",
"indexFilterSet" : false,
"parsedQuery" : {
"cre_carteraId" : {
"$eq" : "31"
}
},
"winningPlan" : {
"stage" : "PROJECTION",
"transformBy" : {
"cre_tramoMora" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"cre_carteraId" : 1,
"cre_periodo" : 1,
"cre_tramoMora" : 1,
"cre_inactivo" : 1
},
"indexName" : "cartPerTramInact",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"cre_carteraId" : [
"["31", "31"]"
],
"cre_periodo" : [
"[MinKey, MaxKey]"
],
"cre_tramoMora" : [
"[MinKey, MaxKey]"
],
"cre_inactivo" : [
"[MinKey, MaxKey]"
]
}
}
},
"rejectedPlans" : [
{
"stage" : "PROJECTION",
"transformBy" : {
"cre_tramoMora" : 1,
"_id" : 0
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"cre_carteraId" : 1,
"cre_tramoMora" : 1
},
"indexName" : "cartPerTramTest",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"cre_carteraId" : [
"["31", "31"]"
],
"cre_tramoMora" : [
"[MinKey, MaxKey]"
]
}
}
}
]
}
}
},
{
"$group" : {
"_id" : {
"ca_tramomora" : "$cre_tramoMora"
},
"count" : {
"$sum" : {
"$const" : 1.0
}
}
}
}
],
"ok" : 1.0
}
那么,为什么优化器更喜欢较少调整的索引呢?indexFilterSet(为索引过滤的结果)是否为真?
如何改进这个索引,或者查询出了问题?
我没有太多的经验与mongoDB,我感谢任何帮助
只要你有索引cartPerTramInact,优化器就不会使用你的cartPerTramTest索引,因为第一个字段是相同的,并且顺序相同。
这也适用于其他索引。当索引有相同顺序的键时(比如a.b.c.d, a.b.d, a.b)你查询使用字段a.b,它会支持a.b.c.d,反正你不需要索引a.b因为你已经有两个索引涵盖了a.b (a.b.c.d和a.b.d)索引a.b.d仅在您使用这些字段a.b.d进行查询时使用,但是如果a.b.b已经非常有选择性,可能使用索引a.b.c.d只使用部分a.b并进行"全表扫描"以查找d
聚合有一个hint
选项,可以帮助索引…
看到https://www.mongodb.com/docs/upcoming/reference/method/db.collection.aggregate/mongodb-method-db.collection.aggregate