MongoDB как база данных временных рядов - PullRequest
24 голосов
/ 10 сентября 2011

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

Данные временного ряда очень похожи на историю цен акций.У меня есть сбор данных с различных датчиков, взятых с разных машин.Есть значения в миллиардах временных меток, и я хотел бы задать следующие вопросы (предпочтительно из базы данных, а не уровня приложения):

  1. Для данного набора датчиков и временного интервала,Я хочу, чтобы все временные метки и значения датчиков находились в этом интервале по порядку по времени.Предположим, что все датчики имеют одни и те же временные метки (все они были выбраны в одно и то же время).

  2. Для данного набора датчиков и временного интервала я хочу, чтобы каждый k-й элемент (временная метка и соответствующие значения датчика) находились в пределах данного интервала по порядку по времени.

Любая рекомендация о том, как лучше всего это настроить и выполнить запросы?

Спасибо за предложения.

Ответы [ 2 ]

17 голосов
/ 31 января 2014

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

Представьте, что вы храните данные каждую минуту. Рассмотрим следующую структуру документа:

{
  timestamp: ISODate("2013-10-10T23:06:37.000Z"),
  type: ”spot_EURUSD”,
  value: 1.2345
},
{
  timestamp: ISODate("2013-10-10T23:06:38.000Z"),
  type: ”spot_EURUSD”,
  value: 1.2346
}

Это сопоставимо со стандартным реляционным подходом. В этом случае вы создаете один документ на каждое записанное значение, что вызывает много операций вставки. Мы можем сделать лучше. Учтите следующее:

{
  timestamp_minute: ISODate("2013-10-10T23:06:00.000Z"),
  type: “spot_EURUSD”,
  values: {
    0: 1.2345,
    …  
    37: 1.2346,
    38: 1.2347,
    … 
    59: 1.2343
  }
}

Теперь мы можем написать один документ и выполнить 59 обновлений. Это намного лучше, потому что обновления являются атомарными, отдельные записи меньше, и есть другие преимущества производительности и параллелизма. Но что, если бы мы хотели хранить весь день, а не только все часы, в одном документе. Это тогда потребовало бы, чтобы мы пошли вдоль 1440 записей, чтобы получить последнее значение. Чтобы улучшить это, мы можем расширить до следующего:

{
  timestamp_hour: ISODate("2013-10-10T23:00:00.000Z"),
  type: “spot_EURUSD”,
  values: {
    0: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343},
    1: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343},
    …,
    22: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343},
    23: { 0: 1.2343, 1: 1.2343, …, 59: 1.2343}
  }
}

Используя этот вложенный подход, теперь нам нужно только пройти максимум 24 + 60, чтобы получить самое последнее значение в день.

Если мы создаем документы со всеми значениями, заполненными заранее заполнением, мы можем быть уверены, что документ не изменит размер и, следовательно, не будет перемещен.

13 голосов
/ 10 сентября 2011

Если вам не нужно хранить данные вечно (то есть вы не против их «старения»), вы можете рассмотреть «ограниченный сбор». У ограниченных коллекций есть ряд ограничений, которые, в свою очередь, предоставляют некоторые интересные преимущества, которые звучат так, будто они вполне соответствуют тому, что вы хотите.

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

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

Кстати, насколько отличаются датчики и данные, которые они производят? Если они относительно похожи, я бы посоветовал хранить их в одной коллекции для простоты использования - в противном случае разделите их.

Если вы используете одну коллекцию, тогда оба ваших запроса звучат очень выполнимо. Следует иметь в виду, что для получения выгоды от коллекции с ограничениями вам нужно будет выполнять запросы в соответствии с «естественным» порядком коллекций, поэтому запросы с помощью ключа временной метки не будут такими быстрыми. Если показания снимаются через равные промежутки времени (чтобы вы знали, сколько из них будет взято за определенный промежуток времени), я бы предложил что-то вроде следующего для запроса 1:

db.myCollection.find().limit(100000).sort({ $natural : -1 })

Предполагая, например, что вы сохраняете 100 показаний в секунду, приведенное выше вернет данные за последние 100 секунд. Если вам нужны предыдущие 100 секунд, вы можете добавить .skip(100000).

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

Вот документы по Монго на закрытых коллекциях: http://www.mongodb.org/display/DOCS/Capped+Collections

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...