Ho una raccolta MongoDB denominata post
con 35 milioni di oggetti. La raccolta ha due indici secondari definiti come segue.Interrogazione intervallo lento su un indice multitasto
> db.post.getIndexKeys()
[
{
"_id" : 1
},
{
"namespace" : 1,
"domain" : 1,
"post_id" : 1
},
{
"namespace" : 1,
"post_time" : 1,
"tags" : 1 // this is an array field
}
]
mi aspetto la seguente query, che filtra semplicemente namespace
e post_time
, per l'esecuzione in un tempo ragionevole, senza la scansione di tutti gli oggetti.
>db.post.find({post_time: {"$gte" : ISODate("2013-04-09T00:00:00Z"), "$lt" : ISODate("2013-04-09T01:00:00Z")}, namespace: "my_namespace"}).count()
7408
Tuttavia, ci vuole MongoDB almeno dieci minuti per recuperare il risultato e, curiosamente, si riesce ad eseguire la scansione 70 milioni oggetti per fare il lavoro in base alla funzione 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"
}
La differenza tra il numero di oggetti e il numero di scansioni deve essere causata dalle lunghezze delle matrici di tag (che sono tutti uguali a 2). Tuttavia, non capisco perché il filtro post_time
non faccia uso dell'indice.
Puoi dirmi cosa potrei mancare?
(Sto lavorando su una macchina di discesa con 24 core e 96 GB di RAM Sto usando MongoDB 2.2.3.).
Lo spazio dei nomi ha una cardinalità molto bassa? – Sammaye
Attualmente esiste un solo valore 'namespace', che è quello che sto usando. –
Sì, perché MongoDB deve prima limitare il primo campo, quindi ottiene tutto "mio_namespace' e poi ottiene tutti i documenti tra quella data, ecc. Ecc., Prova a riordinare l'indice in modo che sia il primo post_time – Sammaye