【发布时间】:2012-09-24 16:54:27
【问题描述】:
我无法理解这个问题 - 我有一个分片集群,其中一个分片(分片 2)似乎使用了错误的索引。我通过分片键查询,即站点 ID 和第一次请求时间{ site.id: 1, frt: 1 }。我还有一个关于站点 ID 和上次请求时间的索引。
在这个查询中,我还试图通过我在文档中设置的几个布尔值来限制返回的文档。
阅读有关 Mongo 查询优化器如何工作的文档,这对我来说似乎特别奇怪,因为我查看了返回的解释。文档在这里:Query Optimizer
我还包含了来自 Shard 1 的解释,其中查询按预期返回。最后,如果我使用的站点 ID 没有存储在 Shard 2 上的块,它会使用正确的索引,尽管它没有任何东西可以扫描或返回。为了完整起见,在末尾添加了对此的解释。
任何想法为什么会发生这种情况和/或如果这是一个错误?
基本查询(错误索引):
shard2:PRIMARY> db.visit.find({ "site.id": 128, "frt": { $gte: new Date(2012, 8, 24 ) }, "ue": false, "bot": false }).explain()
{
"cursor" : "BtreeCursor site.id_1_lrt_-1",
"isMultiKey" : false,
"n" : 198,
"nscannedObjects" : 61204,
"nscanned" : 61204,
"nscannedObjectsAllPlans" : 61537,
"nscannedAllPlans" : 61537,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 122,
"nChunkSkips" : 0,
"millis" : 727,
"indexBounds" : {
"site.id" : [
[
128,
128
]
],
"lrt" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
},
"server" : "ip-10-4-211-107:2200"
}
提供提示:
shard2:PRIMARY> db.visit.find({ "site.id": 128, "frt": { $gte: new Date(2012, 8, 24 ) }, "ue": false, "bot": false }).hint("site.id_1_frt_1").explain()
{
"cursor" : "BtreeCursor site.id_1_frt_1",
"isMultiKey" : false,
"n" : 198,
"nscannedObjects" : 486,
"nscanned" : 486,
"nscannedObjectsAllPlans" : 486,
"nscannedAllPlans" : 486,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 5,
"indexBounds" : {
"site.id" : [
[
128,
128
]
],
"frt" : [
[
ISODate("2012-09-24T07:00:00Z"),
ISODate("292278995-01--2147483647T07:12:56.808Z")
]
]
},
"server" : "ip-10-4-211-107:2200"
}
没有额外布尔约束的相同查询(使用正确的索引):
shard2:PRIMARY> db.visit.find({ "site.id": 128, "frt": { $gte: new Date(2012, 8, 24 ) } }).explain()
{
"cursor" : "BtreeCursor site.id_1_frt_1",
"isMultiKey" : false,
"n" : 486,
"nscannedObjects" : 486,
"nscanned" : 486,
"nscannedObjectsAllPlans" : 486,
"nscannedAllPlans" : 486,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 1,
"indexBounds" : {
"site.id" : [
[
128,
128
]
],
"frt" : [
[
ISODate("2012-09-24T07:00:00Z"),
ISODate("292278995-01--2147483647T07:12:56.808Z")
]
]
},
"server" : "ip-10-4-211-107:2200"
}
在分片 1 上,原始查询使用预期索引:
shard1:PRIMARY> db.visit.find({ "site.id": 253, "frt": { $gte: new Date(2012, 8, 24 ) }, "ue": false, "bot": false }).explain()
{
"cursor" : "BtreeCursor site.id_1_frt_1",
"isMultiKey" : false,
"n" : 15615,
"nscannedObjects" : 15950,
"nscanned" : 15950,
"nscannedObjectsAllPlans" : 16152,
"nscannedAllPlans" : 16152,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 125,
"nChunkSkips" : 0,
"millis" : 237,
"indexBounds" : {
"site.id" : [
[
253,
253
]
],
"frt" : [
[
ISODate("2012-09-24T07:00:00Z"),
ISODate("292278995-01--2147483647T07:12:56.808Z")
]
]
},
"server" : "ip-10-6-50-253:2100"
}
在 Shard 2 上查询此处没有块的站点(使用正确的索引):
shard2:PRIMARY> db.visit.find({ "site.id": 253, "frt": { $gte: new Date(2012, 8, 24 ), "ue": false, "bot": false } }).explain()
{
"cursor" : "BtreeCursor site.id_1_frt_1",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 0,
"nscanned" : 0,
"nscannedObjectsAllPlans" : 0,
"nscannedAllPlans" : 0,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"site.id" : [
[
253,
253
]
],
"frt" : [
[
ISODate("2012-09-24T07:00:00Z"),
ISODate("292278995-01--2147483647T07:12:56.808Z")
]
]
},
"server" : "ip-10-4-211-107:2200"
}
【问题讨论】:
-
tldr?添加到查询时索引会丢失?
-
你的分片键是什么?您提到您的查询
db.visit.find({ "site.id": 128, "frt": { $gte: new Date(2012, 8, 24 ) }, "ue": false, "bot": false }).explain()在“Shard2”上命中了错误的索引,但您没有包括在“Shard1”上运行此查询的输出。所有针对“Shard1”的查询都是针对"site.id" 128。您能否针对“Shard1”运行“128”查询。 -
上面提到过,分片键是 { site.id: 1, frt: 1 },分片在我尝试使用的同一索引上。在 Shard 1 上运行对
"site.id" 128的查询仍然使用正确的索引,但由于块的拆分方式,该站点没有数据。我选择"site.id": 253作为上面 Shard 1 的示例,因为我知道那里有数据。 -
认为您可能混淆了上面的示例,“所有针对“Shard1”的查询都是针对“site.id”128。” - 实际上,以上查询都没有查询 Shard 1 上的站点 128...
标签: mongodb indexing sharding optimization