Стратегия индекса mongodb для запроса диапазона с разными полями

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

запрос выглядит как

db.collection.find({start:{$gt:DateTime(...)}, final:{$lt:DateTime(...)}})

Итак, какая лучшая стратегия индексирования для этого сценария?


Кстати, что лучше для производительности - хранить дату как время или как временные метки unix, которая сама по себе является самой длинной стоимостью

Ответ 1

Слишком добавить немного больше для балочного ответа.

Отметка времени и длительная проблема. Как правило, сервер MongoDB не видит разницы. Длина кодирования BSON одинакова (64 бит). Вы можете видеть, что производительность отличается на стороне клиента в зависимости от кодировки драйвера. Например, на стороне Java с использованием драйвера 10gen метка времени отображается как Date, которая намного тяжелее, чем Long. Существуют драйверы, которые пытаются избежать этих накладных расходов.

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

db.collection.ensureIndex({start: 1, final: 1})

Ваш запрос будет выполнять (потенциально много) лучше, если вы выполните запрос:

db.collection.find({start:{$gt:DateTime(...),$lt:DateTime(...)}, 
                    final:{$lt:DateTime(...)}})

Концептуально, если вы думаете об индексах как о дереве, то замкнутый диапазон ограничивает обе стороны дерева вместо одной стороны. Без закрытого диапазона сервер должен "проверять" все записи с start больше, чем временная метка, поскольку она не знает отношения между start и final.

Вы даже можете обнаружить, что производительность запроса не лучше, используя один индекс поля, например:

db.collection.ensureIndex({start: 1})

Большая часть экономии происходит от первой обрезки полей. Случай, когда этого не произойдет, - это когда запрос покрывается индексом или порядок/сортировка для результатов могут быть получены из индекса.

HTH - Rob.

Ответ 2

Вы можете использовать Составной индекс, чтобы создать индекс для нескольких полей.

db.collection.ensureIndex({start: 1, final: 1})

Сравните различные запросы и индексы, используя explain(), чтобы получить максимальную отдачу от своей базы данных