Eu tenho uma consulta (que é muito lenta ~ 2,5s ):
db.markers.find({ latlng: { '$within': { '$box': [ [ -16, -140 ], [ 75, 140 ] ] } } }).sort({_id: -1}).limit(1000)
Quando executo a explicação para esta consulta, recebo
{
"cursor" : "GeoBrowse-box",
"isMultiKey" : false,
"n" : 1000,
"nscannedObjects" : 242331,
"nscanned" : 242331,
"nscannedObjectsAllPlans" : 242331,
"nscannedAllPlans" : 242331,
"scanAndOrder" : true,
"indexOnly" : false,
"nYields" : 1383,
"nChunkSkips" : 0,
"millis" : 2351,
"indexBounds" : {
"latlng" : [ ]
},
"lookedAt" : NumberLong(262221),
"matchesPerfd" : NumberLong(242331),
"objectsLoaded" : NumberLong(242331),
"pointsLoaded" : NumberLong(0),
"pointsSavedForYield" : NumberLong(0),
"pointsChangedOnYield" : NumberLong(0),
"pointsRemovedOnYield" : NumberLong(0),
"server" : "xx:27017"
}
Quando eu removo sort({_id: -1}) a explicação me dá (consulta rápida 5 millis ):
{
"cursor" : "GeoBrowse-box",
"isMultiKey" : false,
"n" : 1000,
"nscannedObjects" : 1000,
"nscanned" : 1000,
"nscannedObjectsAllPlans" : 1000,
"nscannedAllPlans" : 1000,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 5,
"indexBounds" : {
"latlng" : [ ]
},
"lookedAt" : NumberLong(1000),
"matchesPerfd" : NumberLong(1000),
"objectsLoaded" : NumberLong(1000),
"pointsLoaded" : NumberLong(0),
"pointsSavedForYield" : NumberLong(0),
"pointsChangedOnYield" : NumberLong(0),
"pointsRemovedOnYield" : NumberLong(0),
"server" : "xx:27017"
}
Eu tenho índice 2d em latlng, índice desc em _id e índices compostos .
db.markers.ensureIndex({latlng: '2d', _id:-1})
db.markers.ensureIndex({ latlng: '2d' })
db.markers.ensureIndex({ _id: -1 })
O que eu quero alcançar é obter marcadores de uma área específica classificados dos mais recentes.
Alguma idéia ou sugestão de como fazer isso em muito menos tempo do que 2,5 segundos ?
Uma consulta no MongoDB pode usar apenas um índice por vez, portanto, é o caso de um ou outro - não pode usar o índice 2d primeiro e, em seguida, fazer uma classificação no índice _id. Para usar índices tanto para a seleção quanto para a classificação, você precisaria de um índice composto como este:
Tente isso, ou similar e veja como isso impacta os resultados tendo em mente que uma vez definido, você pode remover o índice 2d original para economizar espaço e que este novo índice terá que ser carregado na memória para ser eficiente.
Atualização: conforme mencionado no resumo, o acima não melhorou as coisas e a consulta resultante resulta em um resultado scanAndOrder. Isso também acontece com consultas baseadas em intervalo, conforme explicado nesta excelente postagem no blog:
http://blog.mongolab.com/2012/06/cardinal-ins/
Conforme explicado nessa postagem, a resolução usual para desempenho de consulta baseada em intervalo é alternar a ordem dos índices. No entanto, atualmente isso não é possível com índices geográficos. Já existe um problema do Jira aberto para isso aqui para fins de votação e rastreamento:
https://jira.mongodb.org/browse/SERVER-4247