我在MongoDB中有一個約有350K文件的集合。我有Updated
(降序)和SecondaryCategories
(升序)的複合指數。
db.Content.ensureIndex({ "Updated" : -1, "SecondaryCategories" : 1 },{ "name" : "Updated_SecondaryCategories", "background" : true });
我使用MongoDB的C#驅動程序使用lambda語法來構建查詢:
IQueryable<Content> query = repo.GetAll()
.Where(
x =>
x.SecondaryCategories.ContainsAny(sel) &&
(x.Type == ContentType.News || x.Type == ContentType.FotoNews || x.Type == ContentType.LinkedNews || x.Type == ContentType.MediaNews) &&
x.Texts.Any(y => (int)y.Language == cultureId))
.OrderByDescending(x => x.Updated)
.Skip(skipItems)
.Take(count);
和我得到以下幾點:
db.Content.find({ "$query" : { "SecondaryCategories" : { "$in" : [524, 615, 550, 546, 552, 617, 547, 549, 548, 613, 614, 551, 618, 545] }, "$or" : [{ "Type" : 4 }, { "Type" : 8 }, { "Type" : 32 }, { "Type" : 16 }], "Texts" : { "$elemMatch" : { "Language" : 0 } } }, $orderby: { Updated: -1 }}).limit(20);
查詢大約爲運行1300ms這很慢。現在,當我刪除$query
經營者,我應該得到以下幾點:
db.Content.find({ "SecondaryCategories" : { "$in" : [524, 615, 550, 546, 552, 617, 547, 549, 548, 613, 614, 551, 618, 545] }, "$or" : [{ "Type" : 4 }, { "Type" : 8 }, { "Type" : 32 }, { "Type" : 16 }], "Texts" : { "$elemMatch" : { "Language" : 0 } }}).sort({"Updated" : -1}).limit(20);
該查詢只在1ms內運行。
解釋第一個查詢(用$query
運營商):
db.Content.find({ "$query" : { "SecondaryCategories" : { "$in" : [524, 615, 550, 546, 552, 617, 547, 549, 548, 613, 614, 551, 618, 545] }, "$or" : [{ "Type" : 4 }, { "Type" : 8 }, { "Type" : 32 }, { "Type" : 16 }], "Texts" : { "$elemMatch" : { "Language" : 0 } } }, $orderby: { Updated: -1 }, $explain: 1 }).limit(20).pretty();
{
"cursor" : "BtreeCursor Updated_SecondaryCategories multi",
"isMultiKey" : true,
"n" : 188173,
"nscannedObjects" : 188668,
"nscanned" : 337619,
"nscannedObjectsAllPlans" : 189056,
"nscannedAllPlans" : 338007,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 1,
"nChunkSkips" : 0,
"millis" : 1304,
"indexBounds" : {
"Updated" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"SecondaryCategories" : [
[
524,
524
],
[
545,
545
],
[
546,
546
],
[
547,
547
],
[
548,
548
],
[
549,
549
],
[
550,
550
],
[
551,
551
],
[
552,
552
],
[
613,
613
],
[
614,
614
],
[
615,
615
],
[
617,
617
],
[
618,
618
]
]
}
而對於第二(不$query
運營商):
db.Content.find({ "SecondaryCategories" : { "$in" : [524, 615, 550, 546, 552, 617, 547, 549, 548, 613, 614, 551, 618, 545] }, "$or" : [{ "Type" : 4 }, { "Type" : 8 }, { "Type" : 32 }, { "Type" : 16 }], "Texts" : { "$elemMatch" : { "Language" : 0 } }}).sort({"Updated" : -1}).limit(20).explain();
{
"cursor" : "BtreeCursor Updated_SecondaryCategories multi",
"isMultiKey" : true,
"n" : 20,
"nscannedObjects" : 29,
"nscanned" : 69,
"nscannedObjectsAllPlans" : 94,
"nscannedAllPlans" : 134,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"Updated" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"SecondaryCategories" : [
[
524,
524
],
[
545,
545
],
[
546,
546
],
[
547,
547
],
[
548,
548
],
[
549,
549
],
[
550,
550
],
[
551,
551
],
[
552,
552
],
[
613,
613
],
[
614,
614
],
[
615,
615
],
[
617,
617
],
[
618,
618
]
]
}
我實在無法理解查詢這種行爲差異。它似乎是第一個查詢掃描通過338k文件,並返回188173,這是有限的,而第二個掃描只有69.
我的索引是否錯誤或我必須重寫查詢?如果沒有使用C#MongoDB Driver的$query
運算符,是否有任何方法來編寫查詢?
你試過解釋查詢嗎? http://docs.mongodb.org/manual/reference/operator/meta/query/#op._S_query - 我想你可能需要添加限制條款的查詢文件本身,而不是'.limit' –
是的,我使用'$ explain:1'來解釋第一個查詢。我找不到任何其他限制方式。有'$ maxScan',但它只是限制掃描的文件數量。 – Villu89