2014-02-21 3 views
4

Если я делаю счета запрос, получить результаты в < 2secondsПонимание производительности: Монго агрегацию против подсчета

db.coll.find({"A":1,"createDate":{"$gt":new Date("2011-05-21"),"$lt":new Date("2013-08-21")}}).count() 

При этом используется следующий индекс

db.coll.ensureIndex({"A":1,"createDate":1}) 

Кроме того, есть 4 колонки А , B, C, D (значения всегда равны 0 или 1), для которых я запускаю 4 счета запросов и получаю результаты в < 10 секунд.

Я просмотрел документацию по агрегационной структуре и создал агрегированный запрос для выполнения всех четырех сумм.

db.coll.aggregate( { $match : {"createDate":{$gt:new Date("2013-05-21"),$lt:new Date("2013-08-21")} } }, 
{ $group : 
         { _id:null, 
         totalA : { $sum : "$A" }, 
         totalB : {$sum: "$B}, 
         totalC:{$sum: "$C"}, 
         totalD:{$sum: "$D"}}} 
) 

Я также создал индекс:

db.coll..ensureIndex({"createDate":1,"A":1,"B":1,"C":1,"D":1}) 

Согласно документации, этот показатель охватывает мою агрегатную функцию. Но возврат агрегата составляет ~ 18 секунд.

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

ответ

3

Короткий ответ: в вашем случае агрегирование происходит медленнее, потому что оно связано с большей обработкой данных при использовании индекса mongo эффективно вычислять подсчеты. Агрегация предназначена для вычисления некоторых сложных результатов (grouping и т. Д.), А для простого подсчета count() достаточно.

Причина в том, что агрегация в mongodb является основой для агрегирования данных и основана на концепции трубопроводов обработки данных. Монго логически передает всю коллекцию в конвейер агрегации. По этой причине нет explain для агрегации в целом (начиная с этой записи, версия 2.4). Это означает, что в основном используется один метод доступа, а остальная часть времени используется для обработки. Но, похоже, есть поддержка explainin recent versions.

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

Early Filtering

Если операция агрегации требуется только подмножество данных в коллекции, используйте $match, $limit и $skip этапы ограничить документы, которые поступают на начало трубопровода. При размещении на начала конвейера, операции $ match используют подходящие индексы для сканируют только соответствующие документы в коллекции.

Размещение стадии матча трубопровода $ с последующим $sort стадией в начале трубопровода логически эквивалентен одному запрос с какой и может использовать индекс. Когда возможно, разместите операторы $ match на начале конвейера.

Aggregation pipeline behaviour.

+1

объяснение для агрегации, просто добавьте аргумент {explain: true} после массива конвейера. И вся коллекция не должна передаваться, если есть индекс, который может предоставить необходимые значения. Проблема здесь заключается в том, что агрегация выполняет нечто иное, чем counts, это фактически добавляет значения этих полей, не считая, сколько из них отличных от нуля. –

+0

Он еще не выпущен, но идет в 2.6. –

+0

неправильный, он доступен в текущей версии 2.4.x и уже несколько месяцев. –

6

Во-первых, хотя и не документированы для 2.4.8 вы можете запустить объяснить, используя db.runCommand призывание:

db.runCommand({ 
    aggregate: "coll", 
    pipeline: [  
     { $match : 
      {"createDate":{$gt:new Date("2013-05-21"),$lt:new Date("2013-08-21")} } 
     }, 
     { $group : { 
       _id:null, 
       totalA: {$sum :"$A"}, 
       totalB: {$sum: "$B"}, 
       totalC: {$sum: "$C"}, 
       totalD: {$sum: "$D"} 
     }} 
    ], 
    explain: true 
}) 

который даст вам некоторое представление о том, что происходит.

Кроме того, и в первую очередь, вы сравниваете яблоки в апельсины.

Когда вы выдаете count() по запросу, он использует свойства результата курсора для получения количества согласованных документов.

Под агрегацией вы выбираете расширенный, а затем уплотняете все эти результаты в сумму всех предметов. Если ваш начальный $ матч имеет лотов результатов, то все они должны быть свернуты вместе с суммой.

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

Смежные вопросы