12 July 2013

В MongoDB существует уникальный параметр запроса $maxScan, который я не встречал в других БД. Он имеет следующий синтаксис:

db.collection.find( { <query> } )._addSpecial( "$maxScan" , <number> )
db.collection.find( { $query: { <query> }, $maxScan: <number> } )

Суть его очень проста: в то время как $limit ограничивает число документов, возвращаемых(nreturned) при выполнении запроса, $maxScan ограничивает количество просканированных(nscanned) документов.

Это всё здорово, но где можно использовать такое нестандартное поведение запросов?

Пример из жизни

Представьте себе базу для хранения истории показаний датчиков следующего вида:

{
    datetime: ISODate(...),
    sensor_1: float,
    sensor_2: float,
    ...
    sensor_n: float
}

где datetime - дата снятия показаний, а sensor_i - показания i-го датчика. База очень большая, поэтому для ускорения запросов существует индекс по полю datetime.

Как получить все данные за определенный день:

> db.coll.find({datetime: {$gte: <начало дня>, $lt: <конец дня>}})

Здесь все очень просто: мы делаем поиск по индексу, указав диапазон значений.

Последнее значение, которое отправил i-ый датчик:

> db.coll.find({sensor_i:{$exists: true}}).sort({datetime: -1}).limit(1)

Такой запрос может занять очень много времени, если датчик скидывал свои показания очень давно. Ещё хуже, если датчик ни разу еще не скидывал своих показаний. В этом случае монго придется просканировать все документы в коллекции, что бы в этом убедиться.

Что бы выйти из затруднительного положения и не переделывать схему хранения, можно ограничить свой поиск последними N документами, подразумевая тем самым, что если мы не находим искомое значение в этих N документах, то считаем, что ни одного значения с данного датчика отправлено не было(или данные по нему сильно устарели):

> db.coll.find({ $query: {sensor_i:{$exists: true}}, $maxScan: <N>}).sort({datetime: -1}).limit(1)

Теперь, запросы по коллекции с данными не будет производить полный поиск, а мы избавились о необходимости создавать огромные индексы по всем полям.



blog comments powered by Disqus

Fork me on GitHub