У меня есть 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:
-
- Я прочитал, что каждый осколок должен содержать весь индекс базы данных?
-
- У меня есть опасения, что структура запроса может не вписаться в среду совместного использования. Использование идентификатора продукта в качестве ключа осколка, похоже, соответствует не всем типам запросов, и слишком сложным чередование по категории. Один элемент может быть указан в нескольких основных и подкатегориях.... Мое беспокойство может быть неправильным, я никогда не использовал его в производственной среде.
Но также должны быть другие стратегии оптимизации, тоже не приходило мне в голову, о которых я хотел бы услышать! Какая стратегия оптимизации кажется наиболее перспективной или представляет собой смесь нескольких оптимизаций?