Подтвердить что ты не робот

В MongoDB стратегия максимизации производительности записей в ежедневных журнальных документах

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

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

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

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

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

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

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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" }       } }

Ответ 3

Вы делаете предсказуемое/постоянное количество нажатий в вашем массиве данных. (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 После двух обновлений данных:

 {
          _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 часа.

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