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

MongoDB плохо работает на больших коллекциях с 50 000 000 документов плюс

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

Вот список с количеством документов в логической базе данных:

  • CoUk: 56.719.977
  • De: 61.216.165
  • Fr: 52.280.460
  • Он: 34.422.801

Моя проблема в том, что производительность записи в базе данных становится хуже, особенно пишет в самую большую из четырех баз данных (De) стало очень плохо, согласно iotop в процессе mongod используется 99% времени ввода-вывода с записью менее 3 МБ и 1,5 МБ в секунду. Это приводит к длительной блокировке баз данных, 100% + блокировка становится обычной согласно mongostat - даже если все процессы записи и чтения в базы данных других стран были остановлены. Текущее подчиненное устройство достигает LOAD до 6, мастер установки реплик имеет нагрузку 2-3 одновременно, поэтому он также приводит к задержке репликации.

Каждая база данных имеет одинаковую структуру данных и индексов, я использую самую большую базу данных (De) только для других примеров.

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

{
    "_id" : ObjectId("533b675dba0e381ecf4daa86"),
    "ProductId" : "XGW1-E002F-DW",
    "Title" : "Sample item",
    "OfferNew" : {
        "Count" : 7,
        "LowestPrice" : 2631,
        "OfferCondition" : "NEW"
    },
    "Country" : "de",
    "ImageUrl" : "http://….jpg",
    "OfferHistoryNew" : [ 
        … 
        {
            "Date" : ISODate("2014-06-01T23:22:10.940+02:00"),
            "Value" : {
                "Count" : 10,
                "LowestPrice" : 2171,
                "OfferCondition" : "NEW"
            }
        }
    ],
    "Processed" : ISODate("2014-06-09T23:22:10.940+02:00"),
    "Eans" : [ 
        "9781241461959"
    ],
    "OfferUsed" : {
        "Count" : 1,
        "LowestPrice" : 5660,
        "OfferCondition" : "USED"
    },
    "Categories" : [ 
        NumberLong(186606), 
        NumberLong(541686), 
        NumberLong(288100), 
        NumberLong(143), 
        NumberLong(15777241)
    ]
}

Типичные запросы являются простыми, например, ProductId или EAN, только для уточнений по категории и сортируются по его рангу или уточнениям по категориям и диапазону ранжирования A (например, от 1 до 10.000) и сортируются по B ранг....

Это статистика из наибольшего db:

{
    "ns" : "De.Item",
    "count" : 61216165,
    "size" : 43915150656,
    "avgObjSize" : 717,
    "storageSize" : 45795192544,
    "numExtents" : 42,
    "nindexes" : 6,
    "lastExtentSize" : 2146426864,
    "paddingFactor" : 1,
    "systemFlags" : 0,
    "userFlags" : 1,
    "totalIndexSize" : 41356824320,
    "indexSizes" : {
        "_id_" : 2544027808,
        "RankA_1" : 1718096464,
        "Categories_1_RankA_1_RankB_-1" : 16383534832,
        "Eans_1" : 2846073776,
        "Categories_1_RankA_-1" : 15115290064,
        "ProductId_1" : 2749801376
    },
    "ok" : 1
}

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

Каждая страна DB должна обрабатывать 3-5 миллионов обновлений/вставок в день, моя цель - выполнять операции записи менее чем за пять часов в ночное время.

В настоящее время это набор реплик с двумя серверами, каждый из которых имеет 32 ГБ оперативной памяти и RAID1 с 2 ТБ жесткими дисками. Простые оптимизации, такие как планировщик блокировки и noatime, уже сделаны.

Я разработал несколько стратегий оптимизации:

  • Уменьшение индексов числа:
    • по умолчанию _id может использовать ProductId вместо MongoId по умолчанию, который сэкономит 6-7% на каждый DB за общий размер nixes.
    • Пытаясь удалить индекс Categories_1_RankA_-1, возможно, индекс LookNodes_1_RankA_1_RankB_-1 может обрабатывать запрос. Хорошо ли выполняется сортировка, если не используется полный индекс? Другой способ - сохранить индекс, соответствующий категориям_1_RankA_1_RankB_-1 в другой коллекции, которая относится к основной коллекции.
  • Уменьшение количества необработанных данных с помощью меньших клавиш, вместо "Категории", "Eans", "OfferHistoryNew"... Я мог бы использовать "a", "b", "c"... это должно быть легко, поскольку я использовал http://mongojack.org/, но теперь я не понимаю, насколько это будет полезно.
  • Замена RAID1 на RAID0 может быть легко протестирована, если взять подчиненный, переустановить и прочитать его в наборе реплик...
  • Тестирование более сильных аппаратных SSD и больше памяти, которая должна обрабатывать чтение и запись быстрее.
  • Используйте возможности затенения MongoDB:
    • Я прочитал, что каждый осколок должен содержать весь индекс базы данных?
    • У меня есть опасения, что структура запроса может не вписаться в среду совместного использования. Использование идентификатора продукта в качестве ключа осколка, похоже, соответствует не всем типам запросов, и слишком сложным чередование по категории. Один элемент может быть указан в нескольких основных и подкатегориях.... Мое беспокойство может быть неправильным, я никогда не использовал его в производственной среде.

Но также должны быть другие стратегии оптимизации, тоже не приходило мне в голову, о которых я хотел бы услышать! Какая стратегия оптимизации кажется наиболее перспективной или представляет собой смесь нескольких оптимизаций?

4b9b3361

Ответ 1

Скорее всего, вы столкнулись с проблемами из-за роста записи, см. http://docs.mongodb.org/manual/core/write-performance/#document-growth.

Монго предпочитает записи фиксированного (или, по крайней мере, ограниченного) размера. Увеличение размера записи за пределы предварительно выделенного хранилища приведет к перемещению документа в другое место на диске, умножая ваш ввод-вывод на каждую запись. Рассмотрите предварительное выделение "достаточного" пространства для вашего среднего документа при вставке, если ваши размеры документа относительно однородны. В противном случае рассмотрим разделение быстро растущих вложенных массивов на отдельный сбор, тем самым заменяя обновления на вставки. Также проверьте свою фрагментацию и время от времени планируйте уплотнение своих баз данных, чтобы у вас была более высокая плотность документов на один блок, который сократит жесткие ошибки страницы.

Ответ 2

Можно ли использовать базу данных с лучшей пропускной способностью, поддерживающей документы? Я слышал истории успеха с TokuMX. И FoundationDB (где я инженер) имеет очень хорошую производительность с высококонкурентными нагрузками на запись и большими документами. С удовольствием отвечаем на дополнительные вопросы о FoundationDB.