Mam kolekcję MongoDB o nazwie post
z 35 milionów obiektów. Zbiór ma dwa dodatkowe indeksy zdefiniowane w następujący sposób.Zapytanie o powolne zakresy na indeksie wielostronicowym
> db.post.getIndexKeys()
[
{
"_id" : 1
},
{
"namespace" : 1,
"domain" : 1,
"post_id" : 1
},
{
"namespace" : 1,
"post_time" : 1,
"tags" : 1 // this is an array field
}
]
Spodziewam się następujące zapytanie, które po prostu filtruje przez namespace
i post_time
, aby uruchomić w rozsądnym czasie bez skanowania wszystkich obiektów.
>db.post.find({post_time: {"$gte" : ISODate("2013-04-09T00:00:00Z"), "$lt" : ISODate("2013-04-09T01:00:00Z")}, namespace: "my_namespace"}).count()
7408
Jednak to trwa MongoDB co najmniej dziesięć minut, aby pobrać wynik i, co ciekawe, to udaje skanowanie obiektów, aby wykonać zadanie zgodnie z funkcją explain
.
> db.post.find({post_time: {"$gte" : ISODate("2013-04-09T00:00:00Z"), "$lt" : ISODate("2013-04-09T01:00:00Z")}, namespace: "my_namespace"}).explain()
{
"cursor" : "BtreeCursor namespace_1_post_time_1_tags_1",
"isMultiKey" : true,
"n" : 7408,
"nscannedObjects" : 69999186,
"nscanned" : 69999186,
"nscannedObjectsAllPlans" : 69999186,
"nscannedAllPlans" : 69999186,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 378967,
"nChunkSkips" : 0,
"millis" : 290048,
"indexBounds" : {
"namespace" : [
[
"my_namespace",
"my_namespace"
]
],
"post_time" : [
[
ISODate("2013-04-09T00:00:00Z"),
ISODate("292278995-01--2147483647T07:12:56.808Z")
]
],
"tags" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "localhost:27017"
}
Różnica między liczbą obiektów, a liczba skanów musi być spowodowane przez długościach macierzy bramek (które są wszystkie równe 2). Nadal nie rozumiem, dlaczego filtr post_time
nie korzysta z indeksu.
Czy możesz mi powiedzieć, czego może mi brakować?
(pracuję na maszynie schodzenia z 24 rdzeni i 96 GB RAM Używam MongoDB 2.2.3.).
Czy przestrzeń nazw ma bardzo niską liczebność? – Sammaye
Obecnie istnieje tylko jedna odrębna wartość 'namespace', której używam. –
Dlatego MongoDB musi najpierw ograniczyć na pierwszym polu, więc pobiera wszystkie 'my_namespace', a następnie pobiera wszystkie dokumenty między tą datą, itd. Itd., Spróbuj zmienić kolejność indeksów, aby czas post_time był pierwszy. – Sammaye