У нас есть проблема запросов агрегации, работающих длительное время (пару минут).
Коллекция:
У нас есть коллекция из 250 миллионов документов с примерно 20 полями на документ, Общий размер коллекции составляет 110 ГБ.
У нас есть индексы над полями "our_id" и dtKey.
Оборудование:
Память:ОЗУ 24 ГБ (6 * 4 ГБ DIMMS 1333 МГц)
диск:Lvm 11TB, построенный из 4 дисков 3TB дисков:
-
Максимальные мгновенные передачи данных 600 МБ/с.
-
Шпиндель 7200 об/мин. Средняя латентность = 4.16 мс
- RAID 0
CPU:
2 * E5-2420 0 @1,90 ГГц Всего 12 ядер с 24 потоками. Dell R420.
Проблема: Мы пытаемся сделать запрос агрегирования следующего:
db.our_collection.aggregate(
[
{
"$match":
{
"$and":
[
{"dtKey":{"$gte":20140916}},
{"dtKey":{"$lt":20141217}},
{"our_id":"111111111"}
]
}
},
{
"$project":
{
"field1":1,
"date":1
}
},
{
"$group":
{
"_id":
{
"day":{"$dayOfYear":"$date"},
"year":{"$year":"$date"}
},
"field1":{"$sum":"$field1"}
}
}
]
);
Этот запрос занимает пару минут для запуска, когда он выполняется, мы можем видеть следующее:
- Текущая операция Mongo дает более 300 тысяч раз
- На iostat мы видим ~ 100% использование диска
После выполнения этого запроса он, похоже, находится в кеше, и это можно сделать снова в течение секунды,
После запуска для 3 - 4 пользователей кажется, что первый из них уже выгружен из кэша, и запрос занимает много времени.
Мы проверили счет на соответствующую часть и увидели, что у нас есть пользователи 50K-документов, а также пользователи с документами 500K,
Мы попытались получить только соответствующую часть:
db.pub_stats.aggregate(
[
{
"$match":
{
"$and":
[
{"dtKey":{"$gte":20140916}},
{"dtKey":{"$lt":20141217}},
{" our_id ":"112162107"}
]
}
}
]
);
И запросы, кажется, занимают приблизительно 300-500 М памяти,
Но после запуска полного запроса он, кажется, занимает 3.5 ГБ памяти.
Вопросы:
- Почему конвейерная обработка агрегации занимает столько памяти?
- Как мы можем увеличить нашу производительность, чтобы он работал в разумные сроки для HTTP-запроса?