Ausgabe
Ich möchte wissen:
- Regensumme (mm)
- Sonnensumme (Stunden)
- Wahrscheinlichkeit (%) eines Regentages mit mehr als 0,5 mm Regen am Wochenende
An den Wochenenden (sa+so) zwischen KW 20 bis 40 seit 17 Jahren.
Ich habe 820.000 Dokumente in 10-Minuten-Perioden. Die Anfrage dauerte manchmal 38 Sekunden, manchmal aber auch länger als 1 Minute.
Haben Sie eine Idee, wie Sie die Leistung verbessern können?
Datenmodell:
[
'datum',
'regen',
'tempAussen',
'sonnenSchein',
and more...
]
Schema:
[
{
$project: {
jahr: {
$year: {
date: '$datum',
timezone: 'Europe/Berlin',
},
},
woche: {
$week: {
date: '$datum',
timezone: 'Europe/Berlin',
},
},
day: {
$isoDayOfWeek: {
date: '$datum',
timezone: 'Europe/Berlin',
},
},
stunde: {
$hour: {
date: '$datum',
timezone: 'Europe/Berlin',
},
},
tagjahr: {
$dayOfYear: {
date: '$datum',
timezone: 'Europe/Berlin',
},
},
tempAussen: 1,
regen: 1,
sonnenSchein: 1,
},
},
{
$match: {
$and: [
{
woche: {
$gte: 20,
},
},
{
woche: {
$lte: 40,
},
},
{
day: {
$gte: 6,
},
},
],
},
},
{
$group: {
_id: ['$tagjahr', '$jahr'],
woche: {
$first: '$woche',
},
regen_sum: {
$sum: '$regen',
},
sonnenSchein_sum: {
$sum: '$sonnenSchein',
},
},
},
{
$project: {
_id: '$_id',
regenTage: {
$sum: {
$cond: {
if: {
$gte: ['$regen_sum', 0.5],
},
then: 1,
else: 0,
},
},
},
woche: 1,
regen_sum: 1,
sonnenSchein_sum: 1,
},
},
{
$group: {
_id: '$woche',
regen_sum: {
$sum: '$regen_sum',
},
sonnenSchein_sum: {
$sum: '$sonnenSchein_sum',
},
regenTage: {
$sum: '$regenTage',
},
},
},
{
$project: {
regenTage: 1,
regen_sum: {
$divide: ['$regen_sum', 34],
},
sonnenSchein_sum: {
$divide: ['$sonnenSchein_sum', 2040],
},
probability: {
$divide: ['$regenTage', 0.34],
},
},
},
{
$project: {
regen_sum: {
$round: ['$regen_sum', 1],
},
sonnenSchein_sum: {
$round: ['$sonnenSchein_sum', 1],
},
wahrscheinlich: {
$round: ['$probability', 0],
},
},
},
{
$sort: {
_id: 1,
},
},
]
Dieses Ergebnis ist ein Beispiel für Woche 20: Am Wochenende der Kalenderwoche 20 habe ich im Durchschnitt 2,3 mm Regen, 11,9 Stunden Sonnenschein und eine Wahrscheinlichkeit von 35 %, dass es an mindestens einem Tag des Wochenendes regnen wird
_id:20
regen_sum:2.3
sonnenSchein_sum:11.9
probability:35
Lösung
Ohne die ausführliche EXPLAIN-Ausgabe ( .explain("allPlansExecution")
) ist es schwierig, etwas mit Sicherheit zu sagen. Hier sind einige Beobachtungen aus einem einfachen Blick auf die bereitgestellte Aggregationspipeline (unter „Schema:“).
Before going into observations, I must ask what your specific goals are. Are operations like these something you will be running frequently? Is anything faster than 38 seconds acceptable, or is there a specific runtime that you are looking for? As outlined below, there probably isn’t much opportunity for direct improvement. Therefore it might be beneficial to look into other approaches to the problem, and I’ll outline one at the end.
The first observation is that this aggregation is going to perform a full collection scan. Even if an index existed on the datum
field, it could not be used since the filtering in the $match
is done on new fields that are calculated from datum
. We could make some changes to allow an index to be used, but it probably wouldn’t help. You are processing ~38% of your data (20
of the 52
weeks per year) so the overhead of doing the index scan and randomly fetching a significant portion of the data is probably more than just scanning the entire collection directly.
Secondly, you are currently $group
ing twice. The only reason for this seems to be so that you can determine if a day is considered ‘rainy’ first (more than 0.5mm
of rain). But the ‘rainy day’ indicator then effectively gets combined to become a ‘rainy weekend’ indicator in the second grouping. Although it could technically change the results a little due to the rounding done on the 24 hour basis, perhaps that small change would be worthwhile to eliminate one of the $group
stages entirely?
Wenn dies mein System wäre, würde ich erwägen, einige dieser Daten vorab zu aggregieren. Insbesondere tägliche Zusammenfassungen im Gegensatz zu den 10-Minuten-Intervallen von Rohdaten würden hier wirklich viel dazu beitragen, den Verarbeitungsaufwand zu reduzieren, der zum Erstellen solcher Zusammenfassungen erforderlich ist. Details für jeden Tag (der sich nicht ändert) wären dann in einem einzigen Dokument statt in 144
einzelnen enthalten. Das würde es sicherlich ermöglichen, dass eine Aggregation, die der obigen logisch äquivalent ist, viel schneller verarbeitet wird als das, was Sie derzeit beobachten.
Beantwortet von – user20042973
Antwort geprüft von – Timothy Miller (FixError Admin)