MongoDB, как создать индекс для запроса, содержащий геопространственный запрос, запрос диапазона и сортировку по разным столбцам? - PullRequest
0 голосов
/ 01 февраля 2012

Итак, если у меня есть запрос, который выполняет следующее (в псевдокоде)

find (рядом x, b> y) .sort (c)

где a - геостолбец, b - это тип long, а c - также тип long

Будет ли работать и предлагаться составной индекс для (a: 2d, b: 1, c: 1)?

1 Ответ

2 голосов
/ 01 февраля 2012

У геопространственных запросов есть своя собственная категория индекса (как вы упоминаете), и геохэш значительно повышает производительность индекса при первом поиске ключа - это лучше, чем диапазон, если вы можете правильно его настроить. В любом случае, я думаю, что ваша стратегия сработает: ключом будет установка $ maxDistance на что-то довольно маленькое.

Я вставил 10 миллионов случайных географических записей, чтобы соответствовать вашему описанию, например:

{ "_id" : ObjectId("4f28e1cffc90631d239f8b5a"), "a" : [ 46, 47 ], "b" : ISODate("2012-02-01T06:53:25.543Z"), "c" : 19 }
{ "_id" : ObjectId("4f28e1bdfc90631d239c4272"), "a" : [ 54, 48 ], "b" : ISODate("2012-02-01T06:53:32.699Z"), "c" : 20 }
{ "_id" : ObjectId("4f28e206fc90631d23aac59d"), "a" : [ 46, 52 ], "b" : ISODate("2012-02-01T06:55:14.103Z"), "c" : 22 }
{ "_id" : ObjectId("4f28e1a7fc90631d23995700"), "a" : [ 54, 52 ], "b" : ISODate("2012-02-01T06:52:33.312Z"), "c" : 27 }
{ "_id" : ObjectId("4f28e1d7fc90631d23a0e9e7"), "a" : [ 52, 46 ], "b" : ISODate("2012-02-01T06:53:11.315Z"), "c" : 31 }

С maxDistance на уровне ниже 10 производительность действительно довольно хорошая.

db.test13.find({a:{$near:[50,50], $maxDistance:4}, b:{$gt:d}}).sort({c:1}).explain();
{
"cursor" : "GeoSearchCursor",
"nscanned" : 100,
"nscannedObjects" : 100,
"n" : 100,
"scanAndOrder" : true,
"millis" : 25,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {

}
}

Если вы пропустите maxDistance, оно начнет страдать. Для выполнения некоторых запросов потребовалось до 60 секунд. Параметр вторичного диапазона, кажется, не очень помогает, даже если диапазон довольно узок - похоже, все дело в maxDistance.

Я рекомендую вам поэкспериментировать с ним, чтобы понять, как работает геопространственный индекс. Вот мой тестовый цикл вставки. Вы также можете попробовать ограничить биты для меньшего разрешения

function getRandomTime() {
   return new Date(new Date() - Math.floor(Math.random()*1000000));
}

function getRandomGeo() {
   return [Math.floor(Math.random()*360-180),Math.floor(Math.random()*360-180)];
}

function initialInsert() {
   for(var i = 0; i < 10000000; i++) {
      db.test13.save({
         a:getRandomGeo(),
         b:getRandomTime(),
         c:Math.floor(Math.random()*1000)
      });
   }
}
...