2016-03-22 3 views
0

У меня есть коллекция в mongodb. Документы содержат массив. Я хочу знать, сколько элементов существует во всех массивах во всех документах. Есть несколько способов сделать это (в этом вопросе: MongoDB: count the number of items in an array), и я хочу знать, какой метод более эффективен, и как определить, какой метод более эффективен.Подсчитайте элементы в массивах в документах Mongodb: эффективность и производительность

Документы выглядеть следующим образом:

{"foo":[1,2,3,4]} 
{"foo":[5,6,7]} 

я могу получить номер я хочу, запустив либо:

db.countTest.aggregate([{$unwind:"$foo"},{$group:{_id:null,"total foo":{$sum:1}}}]) 

или

db.countTest.aggregate([{$project:{count:{$size:"$foo"}}},{$group:{_id:null,"total foo":{$sum:"$count"}}}]) 

SO мой вопрос: какой метод более эффективен, и как я могу сказать, что более эффективно. Я выполнил агрегированные запросы с помощью {explain: true}, однако я не нашел ничего особенно полезного в выходе. Мое чувство - это второй метод, более эффективный, так как он не требует развязки, но я надеялся, что смогу это доказать. Причина для запроса заключается в том, что этот пример представляет собой сокращенную версию сценария реальной жизни с гораздо более крупными документами.

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

благодарит за вашу помощь.

+0

Classic открытый вопрос. – Saleem

+0

Один метод должен быть более эффективным, чем другой, и запуск агрегата повлияет на производительность базы данных, иначе он не будет. Так что я не уверен, как вопрос открыт? – robjwilkins

+0

Это упрямый вопрос. Вы должны сами оценить производительность и посмотреть, что более эффективно, а что нет. – Saleem

ответ

0

Я создал коллекцию с более чем 1 миллиона документов, каждый ищет, как это:

{ "_id" : ObjectId("56f155f6006ec8ceeec407ec"), "foo" : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ] } 

Я тогда написал JavaScript, который работает различные агрегатные запросы в три раза, вычисляют дельты и распечатывает результаты. Сценарий выглядит следующим образом:

var start = Date.now(); 
db.countTest.aggregate([{$unwind:"$foo"},{$group:{_id:null,"total foo":{$sum:1}}}]) 
var done = Date.now(); 
var delta1 = done - start; 
print(delta1); 
var start = Date.now(); 
db.countTest.aggregate([{$unwind:"$foo"},{$group:{_id:null,"total foo":{$sum:1}}}]) 
var done = Date.now(); 
var delta2 = done - start; 
print(delta2); 
var start = Date.now(); 
db.countTest.aggregate([{$unwind:"$foo"},{$group:{_id:null,"total foo":{$sum:1}}}]) 
var done = Date.now(); 
var delta3 = done - start; 
print(delta3); 
var avDelta = (delta1 + delta2 + delta3)/3; 
print ("$Unwind query: average query duration (millis):" + avDelta); 

var start = Date.now(); 
db.countTest.aggregate([{$project:{count:{$size:"$foo"}}},{$group:{_id:null,"total foo":{$sum:"$count"}}}]) 
var done = Date.now(); 
var delta1 = done - start; 
print(delta1); 
var start = Date.now(); 
db.countTest.aggregate([{$project:{count:{$size:"$foo"}}},{$group:{_id:null,"total foo":{$sum:"$count"}}}]) 
var done = Date.now(); 
var delta2 = done - start; 
print(delta2); 
var start = Date.now(); 
db.countTest.aggregate([{$project:{count:{$size:"$foo"}}},{$group:{_id:null,"total foo":{$sum:"$count"}}}]) 
var done = Date.now(); 
var delta3 = done - start; 
print(delta3); 
var avDelta = (delta1 + delta2 + delta3)/3; 
print ("$Size query: average query duration (millis):" + avDelta); 

Это возвращает следующие результаты:

MongoDB shell version: 3.2.0 
connecting to: test 
2630 
2573 
2563 
$Unwind query: average query duration (millis):2588.6666666666665 
2026 
2107 
2003 
$Size query: average query duration (millis):2045.3333333333333 

Я побежал несколько раз и размотки запрос был последовательно медленнее. Было бы интересно узнать, какая разница из более крупных документов, так как выполнение аналогичного запроса к производственной коллекции с более сложными документами размером более 250 000 занимает значительно больше 2-3 секунд.