gpt4 book ai didi

mongodb - gte、lte 和 sort 在不同领域的索引

转载 作者:可可西里 更新时间:2023-11-01 10:04:13 28 4
gpt4 key购买 nike

我对 mongodb 的查询是:

   db.records.find({ from_4: { '$lte': 7495 }, to_4: { '$gte': 7495 } }).sort({ from_11: 1 }).skip(60000).limit(100).hint("from_4_1_to_4_-1_from_11_1").explain()

我建议它应该使用索引 from_4_1_to_4_-1_from_11_1

{
"from_4": 1,
"to_4": -1,
"from_11": 1
}

但出现错误:

error: {
"$err" : "Runner error: Overflow sort stage buffered data usage of 33555322 bytes exceeds internal limit of 33554432 bytes",
"code" : 17144
} at src/mongo/shell/query.js:131

如何避免这个错误?

也许我应该创建另一个索引,它更适合我的查询。

我也尝试了所有升序字段的索引......

{
"from_4": 1,
"to_4": 1,
"from_11": 1
}

...但同样的错误。

P.S. 我注意到,当我删除 skip 命令时......

> db.records.find({ from_4: { '$lte': 7495 }, to_4: { '$gte': 7495 } }).sort({ from_11: 1 }).limit(100).hint("from_4_1_to_4_-1_from_11_1").explain()

...没关系,我得到解释输出,但它说我不使用索引:"indexOnly": false

{
"clauses" : [
{
"cursor" : "BtreeCursor from_4_1_to_4_-1_from_11_1",
"isMultiKey" : false,
"n" : 100,
"nscannedObjects" : 61868,
"nscanned" : 61918,
"scanAndOrder" : true,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"from_4" : [
[
-Infinity,
7495
]
],
"to_4" : [
[
Infinity,
7495
]
],
"from_11" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor ",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 0,
"nscanned" : 0,
"scanAndOrder" : true,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"from_4" : [
[
-Infinity,
7495
]
],
"to_4" : [
[
Infinity,
7495
]
],
"from_11" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
}
],
"cursor" : "QueryOptimizerCursor",
"n" : 100,
"nscannedObjects" : 61868,
"nscanned" : 61918,
"nscannedObjectsAllPlans" : 61868,
"nscannedAllPlans" : 61918,
"scanAndOrder" : false,
"nYields" : 832,
"nChunkSkips" : 0,
"millis" : 508,
"server" : "myMac:27026",
"filterSet" : false
}

P.P.S 我已阅读mongo db tutorial about sort indexes并认为我做得很好。

更新

根据 @dark_shadow 的建议,我又创建了 2 个索引:

db.records.ensureIndex({from_11: 1})

db.records.ensureIndex({from_11: 1, from_4: 1, to_4: 1})

和索引 db.records.ensureIndex({from_11: 1}) 成为我需要的:

db.records.find({ from_4: { '$lte': 7495 }, to_4: { '$gte': 7495 } }).sort({ from_11: 1 }).skip(60000).limit(100).explain()
{
"cursor" : "BtreeCursor from_11_1",
"isMultiKey" : false,
"n" : 100,
"nscannedObjects" : 90154,
"nscanned" : 90155,
"nscannedObjectsAllPlans" : 164328,
"nscannedAllPlans" : 164431,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 1284,
"nChunkSkips" : 0,
"millis" : 965,
"indexBounds" : {
"from_11" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "myMac:27025",
"filterSet" : false
}

最佳答案

当您使用范围查询(并且您是)mongo 查询时,无论如何不要使用索引进行排序。测试查询后,您可以通过查看 explain() 的“scanAndOrder”值来检查这一点。如果该值存在并且为真,则意味着它将在内存中对结果集进行排序(扫描和排序),而不是直接使用索引。这就是您在第一个查询中遇到错误的原因。

正如 Mongodb 文档所说,

对于不使用索引的内存排序,sort() 操作要慢得多。 sort() 操作在使用 32 MB 内存时将中止。

您可以使用 limit(100) 进行内存排序,从而在您的第一个查询中检查 scanAndOrder 的值。

您的第二个查询有效,因为您使用了限制,因此它只会对 100 个可以在内存中完成的文档进行排序。

为什么 "indexOnly": false

这只是表示您希望返回的所有字段都不在索引中,BtreeCursor 表示索引已用于查询(BasicCursor 表示它没有)。对于 indexOnly 查询,您需要在投影中仅返回索引中的那些字段(即:{_id : 0,from_4 :1, to_4:1, from_11 :1 })。这意味着它永远不必触及数据本身,并且可以仅从索引中返回您需要的所有内容。一旦您修改了仅返回提到的字段的查询,您也可以使用解释来检查这一点。

现在,你会感到困惑。它是否使用索引?对于排序,它不会使用索引,但对于查询它正在使用索引。这就是您获得 BtreeCusrsor 的原因(您也应该在其中看到您的索引名称)。

现在,要解决您的问题,您可以创建两个索引:

{
"from_4": 1,
"to_4": 1,
}

{
"from_11" : 1
}

然后通过仔细观察 scanOrder 值,看看它现在是否给出错误或使用您的索引进行排序。

还有一种解决方法:改变化合物索引的顺序:

{
"FROM_11" : 1,
"from_4": 1,
"to_4": 1,
}

不确定这种方法。它应该很有希望地工作。

看看你想要得到什么,你也可以使用 {from_11:-1}.limit(1868) 进行排序。

我希望我现在让事情变得更清楚了。请根据我的建议做一些测试。如果您遇到任何问题,请告诉我。我们可以解决这个问题。

谢谢

关于mongodb - gte、lte 和 sort 在不同领域的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24690812/

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