В моем предыдущем посте я продемонстрировал, как быстро вы можете вставить 50 миллионов записей о временных событиях с MongoDB. На этот раз мы будем использовать все эти данные для подпитки наших тестов агрегации.
Вот так выглядит одна запись события времени:
|
1
2
3
4
5
|
{ "_id" : ObjectId("529a2a988cccdb538932d31f"), "created_on" : ISODate("2012-05-02T06:08:47.835Z"), "value" : 0.9270193106494844} |
Помимо индекса первичного ключа по умолчанию «_id», мы также создали один для поля «create_on», так что это все наши индексы:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
[ { "v" : 1, "key" : { "_id" : 1 }, "ns" : "random.randomData", "name" : "_id_" }, { "v" : 1, "key" : { "created_on" : 1 }, "ns" : "random.randomData", "name" : "created_on_1" }] |
Теперь давайте используем все 50 миллионов записей для создания ежедневного отчета, подсчитывая, сколько событий было сгенерировано за день, включая минимальное, максимальное и среднее значение для этого конкретного дня.
Вот как выглядит наш скрипт:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
var start = new Date();var dataSet = db.randomData.aggregate([ { $group: { "_id": { "year" : { $year : "$created_on" }, "dayOfYear" : { $dayOfYear : "$created_on" } }, "count": { $sum: 1 }, "avg": { $avg: "$value" }, "min": { $min: "$value" }, "max": { $max: "$value" } } }, { $sort: { "_id.year" : 1, "_id.dayOfYear" : 1 } }]);if(dataSet.result != null && dataSet.result.length > 0) { print("Aggregated:" + dataSet.result.length + " days."); db.dailyReport.insert(dataSet.result);}var end = new Date();print("Aggregation took:" + (end.getTime() - start.getTime())/1000 + "s"); |
После объединения всех данных результаты сохраняются в новой коллекции dailyReport. Давайте запустим скрипт и посмотрим, что мы получим:
|
1
2
3
4
5
|
D:\wrk\vladmihalcea\mongodb-facts\aggregator\timeseries>mongo random aggregate_daily_report.jsMongoDB shell version: 2.4.6connecting to: randomAggregated:367 days.Aggregation took:129.052s |
Итак, за 129 секунд нам удалось построить наш отчет для всех этих данных. Давайте проверим новую коллекцию и посмотрим наши ежедневные отчеты.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
{ "_id" : { "year" : 2012, "dayOfYear" : 1 }, "count" : 137244, "avg" : 0.5009360724400802, "min" : 0.0000013632234185934067, "max" : 0.9999953350052238}{ "_id" : { "year" : 2012, "dayOfYear" : 2 }, "count" : 136224, "avg" : 0.49982110975583033, "min" : 0.0000023238826543092728, "max" : 0.9999841095414013} |
Так как мы сгенерировали наши значения, связанные с событием времени, используя Math.random (), мы все равно ожидали среднего, минимального и максимального значений Что действительно интересно, так это то, как быстро MongoDB удалось собрать все эти данные со скоростью 387440 документов в секунду.
Порадовавшись этому результату, давайте теперь проверим, как быстро мы можем случайным образом выбрать отчет за один час. Сначала мы сопоставляем интервал записей в один час, затем группируем и сортируем, чтобы наконец отобразить результаты в оболочке Mongo.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
var minDate = new Date(2012, 0, 1, 0, 0, 0, 0);var maxDate = new Date(2013, 0, 1, 0, 0, 0, 0);var delta = maxDate.getTime() - minDate.getTime();var fromDate = new Date(minDate.getTime() + Math.random() * delta);fromDate.setHours(0, 0, 0, 0);var toDate = new Date(fromDate.getTime() + 60 * 60 * 1000);print("Aggregating from " + fromDate + " to " + toDate);var start = new Date();var dataSet = db.randomData.aggregate([ { $match: { "created_on" : { $gte: fromDate, $lt : toDate } } }, { $group: { "_id": { "year" : { $year : "$created_on" }, "dayOfYear" : { $dayOfYear : "$created_on" }, "hour" : { $hour : "$created_on" } }, "count": { $sum: 1 }, "avg": { $avg: "$value" }, "min": { $min: "$value" }, "max": { $max: "$value" } } }, { $sort: { "_id.year" : 1, "_id.dayOfYear" : 1, "_id.hour" : 1 } }]);if(dataSet.result != null && dataSet.result.length > 0) { dataSet.result.forEach(function(document) { printjson(document); });}var end = new Date();print("Aggregation took:" + (end.getTime() - start.getTime())/1000 + "s"); |
Запустив этот скрипт, мы получим следующий результат:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
D:\wrk\vladmihalcea\mongodb-facts\aggregator\timeseries>mongo random aggregate_hour_report.jsMongoDB shell version: 2.4.6connecting to: randomAggregating from Mon Jul 16 2012 00:00:00 GMT+0300 (GTB Daylight Time) to Mon Jul 16 2012 01:00:00 GMT+0300 (GTB Daylight Time){ "_id" : { "year" : 2012, "dayOfYear" : 197, "hour" : 21 }, "count" : 5808, "avg" : 0.5015344015735451, "min" : 0.00005716201849281788, "max" : 0.9998941225931048}Aggregation took:0.209s |
Это настолько быстро, что мне даже не нужно предварительно рассчитывать почасовые отчеты, а это значит, что я могу легко генерировать их по требованию во время выполнения.
Структура агрегирования MongoDB чрезвычайно полезна, и ее производительность не может остаться незамеченной. Я показал вам только простые примеры, которые не требуют дополнительной оптимизации, чтобы продемонстрировать готовую производительность MongoDB.
- Код доступен на GitHub .