В MongoDB - стратегия максимизации производительности записи в документы ежедневного журнала. - PullRequest
13 голосов
/ 04 ноября 2011

У нас есть коллекция данных журнала, где каждый документ в коллекции идентифицируется по MAC-адресу и календарному дню. В основном:

{
  _id: <generated>,
  mac: <string>,
  day: <date>,
  data: [ "value1", "value2" ]
}

Каждые пять минут мы добавляем новую запись журнала в массив данных в документе текущего дня. Документ переворачивается в полночь по UTC, когда мы создаем новый документ для каждого MAC.

Мы заметили, что IO, измеряемое записанными байтами, увеличивается весь день, а затем падает обратно в полночь по UTC. Этого не должно быть, потому что скорость сообщений журнала постоянна. Мы считаем, что неожиданное поведение связано с перемещением документов Mongo, а не обновлением их массивов журналов. Для чего стоит, stats() показывает, что paddingFactor равен 1.0299999997858227.

Несколько вопросов:

  1. Есть ли способ подтвердить, обновляется ли Mongo на месте или перемещается? Мы видим некоторые шаги в медленном журнале запросов, но это похоже на неподтвержденную информацию. Я знаю, что могу db.setProfilingLevel(2), затем db.system.profile.find() и, наконец, искать "moved:true", но я не уверен, нормально ли это делать в загруженной производственной системе.
  2. Размер каждого документа очень предсказуемый и регулярный. Если предположить, что монго делает много ходов, каков наилучший способ выяснить, почему Монго не может назначать более точно? Или чтобы Монго давил более аккуратно? Если предположить, что приведенное выше описание проблемы является правильным, то изменение коэффициента заполнения не похоже на то, чтобы это помогло.
  3. Мне должно быть достаточно легко запечатлеть документ и удалить любые догадки из Монго. (Я знаю, что коэффициент заполнения документы говорят, что я не должен был этого делать, но мне просто нужно оставить этот вопрос позади меня.) Как лучше всего оформить документ? Кажется простым написать документ с полем массива байтов мусора, а затем немедленно удалить это поле из документа, но есть ли какие-либо ошибки, о которых мне следует знать? Например, я могу представить, что нужно ждать на сервере для операции записи (т.е. выполнить безопасную запись), прежде чем удалять поле мусора.
  4. Я был обеспокоен предварительным распределением всех дневных документов примерно в одно и то же время, потому что кажется, что это насытит диск в это время. Это действительная проблема? Должен ли я попытаться распределить затраты на предварительное распределение за предыдущий день?

Ответы [ 3 ]

4 голосов
/ 22 ноября 2011

Кажется, следующая комбинация приводит к падению производительности записи:

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

Предположительно, ввод / вывод насыщается.Изменение любого из этих факторов, по-видимому, предотвращает это:

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

Кроме того, здесь приведены некоторые другие приемыэто улучшает пропускную способность записи.За исключением шардинга, мы обнаружили, что улучшения были постепенными, в то время как мы пытались решить проблему «это не работает вообще», но я включаю их здесь на случай, если вы ищете дополнительные улучшения.,Ребята из 10Gen провели некоторое тестирование и получили аналогичные результаты :

  1. Shard.
  2. Разбейте длинные массивы на несколько массивов, чтобы ваша общая структура выглядела каквложенное дерево.Если вы используете час дня в качестве ключа, то документ ежедневного журнала становится:{"0":[...], "1":[...],...,"23":[...]}.
  3. Попробуйте ручное распределение.(Это не помогло нам. Похоже, отступы Монго работают так, как рекламировалось. Мой первоначальный вопрос был ошибочным.)
  4. Попробуйте другие значения --syncdelay.(Это нам не помогло.)
  5. Попробуйте без безопасных записей.(Мы уже делали это для данных журнала, и во многих ситуациях это невозможно. Кроме того, это похоже на обман.)

Вы заметите, что я скопировал некоторыеиз предложений от 10Gen здесь, только для полноты.Надеюсь, я сделал это точно!Если они опубликуют пример поваренной книги, я выложу здесь ссылку.

0 голосов
/ 05 ноября 2011

Вы делаете предсказуемое / постоянное число нажатий в массиве данных. (24 * 60) / 5 = 288 за один день. Я настоятельно рекомендую предварительно выделить массив 288 элементов (или 1000 для гибкости и расширения в случае, если вы решите делать это, например, каждые 3 минуты), а затем обновлять документ соответствующим образом для каждого добавления ввода данных. Вот как это сделать:

-Добавьте еще 1 ключ к каждому документу, он сохранит номер ключа для обновления в ассоциативном массиве data. например. Первоначально документ будет выглядеть при первой вставке или обновлении массив данных по обновлению:

{
      _id: <generated>,
      mac: <string>,
      day: <date>,
      data: { "1" : "myGarbageValue","2" : "myGarbageValue",
              "3" : "myGarbageValue"....."1000": "myGarbageValue" }
      n: 1
}

Для каждого обновления вы должны выполнить upsert на data ключе, равном n, и увеличить n После 2 обновлений данных:

 {
          _id: <generated>,
          mac: <string>,
          day: <date>,
          data: { "1" : "myFirstValue","2" : "mySecondValue",
                  "3" : "myGarbageValue"....."1000": "myGarbageValue" }
          n: 3
    }

Плюсы:

  • Меньше роста документа, было бы лучше, если бы ваши myGarbageValue, myFirstValue, mySecondValue были согласованы по размеру и формату.
  • n всегда сообщает вам текущий размер массива data и позволяет выполнять запросы диапазона, чтобы найти размер массива data, который был невозможен в вашей предыдущей структуре, поскольку оператор $ size может возвращать только точное совпадение размера , не варьируется. http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24size
  • Производительность при вставке лучше, когда документ не раскрывается. Здесь это чистое основанное на чистом ключе upsert, например, data.23, тогда как в старой структуре это был $push, который имеет линейную производительность вставки и замедляется по мере роста массива data.

Минусы:

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

Надеюсь, эти предложения помогут. Попробуйте, и сообщите всем нам, приносит ли это вам пользу.

0 голосов
/ 04 ноября 2011

mongodb будет пытаться адаптировать документы адаптивно, поскольку он узнает, как вы обновляете документы в течение определенного периода времени. Более подробную информацию можно найти на http://www.mongodb.org/display/DOCS/Padding+Factor

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

В вашем случае кажется, что вы должны быть в состоянии сделать это, учитывая тот факт, что число выборок в день является постоянным (для вашего 5-минутного интервала.) Можете ли вы напечатать вывод из db. {Yourcollectionname}. stats ()?

Относительно пункта № 4: Вы можете распределить расходы, как вы упомянули, но я бы попробовал вставить документы, когда они вам понадобятся в первый раз, чтобы посмотреть, как они работают, а затем попробовать другие вещи.

Вы, возможно, можете обойти эту конкретную проблему, исследуя другие схемы, но я не уверен, что все, что вы пробовали. Сохраняете ли вы пары ключ-значение в массиве с ключом времени? пример модификации будет переход к чему-то вроде: { id: 1, метрики: { "00:05": {"metric1": "value1"}, "00:10": {"metric2": "value2"} } } * +1010 *

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