2011-02-09 3 views
4

Я использую MongoDB как временный магазин журналов. Коллекция получает ~ 400 000 новых строк в час. Каждая строка содержит временную метку UNIX и строку JSON.Коллекция MongoDB, используемая для данных журнала: индекс или нет?

Периодически я хотел бы скопировать содержимое коллекции в файл на S3, создав файл за каждый час, содержащий ~ 400 000 строк (например, today_10_11.log содержит все строки, полученные между 10:00 и 11:00). Мне нужно сделать эту копию, пока коллекция получает вставки.

Мой вопрос: каково влияние производительности на индекс в столбце timestamp на 400 000 часовых вставок стихов дополнительное время, которое потребуется, чтобы запросить количество часов в строках.

Данное приложение используется в Ruby, запущенном на Heroku, и с использованием плагина MongoHQ.

ответ

4

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

Чтобы получить время создания объекта ид в рубине:

ruby-1.9.2-p136 :001 > id = BSON::ObjectId.new 
=> BSON::ObjectId('4d5205ed0de0696c7b000001') 
ruby-1.9.2-p136 :002 > id.generation_time 
=> 2011-02-09 03:11:41 UTC 

Чтобы генерировать идентификаторы объектов в течение заданного времени:

ruby-1.9.2-p136 :003 > past_id = BSON::ObjectId.from_time(1.week.ago) 
=> BSON::ObjectId('4d48cb970000000000000000') 

Так, например, если вы хотите, чтобы загрузить все документы, вставленные на прошлой неделе, вы просто искали _ids больше, чем past_id и меньше id. Таким образом, через драйвер Ruby:

collection.find({:_id => {:$gt => past_id, :$lt => id}}).to_a 
=> #... a big array of hashes. 

Вы можете, конечно, также добавить отдельное поле для отметок времени, и индекс, но нет смысла брать, что производительность удар, когда Монго уже делает необходимую работу для Вас с полем по умолчанию _id.

More information on object ids.

+0

Это хороший совет о дате в BSON ID. У меня должен был быть отметчик времени, потому что я также импортировал много старых журналов, где дата вставки не была датой события. Но я думаю, что для приложения здесь ваше решение, вероятно, будет хорошим. –

1

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

Рассмотрите возможность хранения метки времени в поле _id вместо объекта MongoDB ObjectId. Пока вы сохраняете уникальные отметки времени, вы здесь будете в порядке. _id не обязательно должен быть ObjectID, но имеет автоматический индекс на _id. Это может быть вашим лучшим выбором, так как вы не добавите дополнительную нагрузку на индекс.

1

Я бы использовал ограниченную коллекцию, неиндексированную, с пространством для, скажем, 600 тыс. Строк, чтобы разрешить слякоть. Один раз в час выгружайте коллекцию в текстовый файл, затем используйте grep для фильтрации строк, которые не относятся к вашей заданной дате. Это не позволяет вам использовать хорошие биты БД, но это означает, что вам не нужно когда-либо беспокоиться о индексах коллекции, флешах или любом из этих глупостей. Критически важный для этого бит хранит сбор бесплатно для вставок, поэтому, если вы можете сделать «жесткий» бит (фильтрация по дате) вне контекста БД, вы не должны иметь заметного влияния на производительность. Строки текста 400-600k тривиальны для grep и, вероятно, не должны занимать больше секунды или два.

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

4

У меня есть приложение, подобное вашему, и в настоящее время оно содержит 150 миллионов записей журнала. При 400k в час эта БД будет быстро развиваться. 400k вставляет час с индексированием по метке времени будет гораздо более целесообразным, чем выполнение необработанного запроса. У меня нет проблем с вставкой десятков миллионов записей за час с индексированной меткой времени, но если я делаю неиндексированный запрос на метку времени, это занимает пару минут на 4-х серверном осколке (привязка процессора). Индексированный запрос появляется мгновенно. Так что определенно проиндексируйте его, накладные расходы на запись при индексировании не так высоки, и 400 тыс. Записей в час не так много для монго.

Одна вещь, которую вам нужно искать, это размер памяти. На 400 тыс. Записей в час вы делаете 10 миллионов в день. Это будет потреблять около 350 МБ памяти в день, чтобы сохранить этот индекс в памяти. Поэтому, если это произойдет некоторое время, ваш индекс может получить больше памяти.

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

+0

michael, спасибо за ваш совет. Я удаляю записи, поэтому буду следить за работой ввода-вывода. –