From 1a64499a77cafd8a6f486b605bcf3ed0ce2c09fb Mon Sep 17 00:00:00 2001 From: Marcel Schwarz Date: Sun, 17 Jan 2021 22:11:13 +0000 Subject: [PATCH] Update Umsetzung --- Projektarbeit-3/Umsetzung.md | 61 +++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/Projektarbeit-3/Umsetzung.md b/Projektarbeit-3/Umsetzung.md index 712b79f..ad2a798 100644 --- a/Projektarbeit-3/Umsetzung.md +++ b/Projektarbeit-3/Umsetzung.md @@ -140,23 +140,62 @@ Der Aufruf von `api_database.get_all_accidents()` ist nun nur noch eine reine de ### Probleme Zunächst sah alles gut aus und die API war auch entsprechend schnell. Sobald allerdings größere Zeitspannen abgerufen werden, wuchs die Zeit enorm. Folgende Werte wurden im zusammenhang mit einer Bikestation gemessen: -* Abruf von **einem Tag:** ~300ms -* Abruf von **einer Woche:** ~1.25s -* Abruf von **zwei Wochen:** ~12s -* Abruf von **einem Monat:** ~90s -* Abruf von **drei Monaten:** ~7min -* Abruf von **einem Jahr:** Nicht möglich! +| Abrufzeitraum | Durchschnittliche Zeit in Sekunden | +| --- | --- | +| ein Tag | 0.3 | +| eine Woche | 1.25 | +| zwei Wochen | 12 | +| ein Monat | 90 | +| drei Monate | 420 | +| ein Jahr | nicht möglich! | Das würde bedeuten, dass wir nur etwa 10% unseres Datensatzes nutzen könnten. ## Performance +Um die oben genannten Probleme zu beheben wurde enormer Aufwand betrieben! Es wurde mit erweterten Datenbankfeatures getesten und sogar das Datenbank System gewechselt. Nichts half auf anhieb. Es blieb nur noch eine Möglichkeit, das kluge Vorberechnen von Werten. +Schnell stelle sich heraus, dass der Datumvergleich sehr lange dauert. Es wurde viel Zeit damit verbracht, den Timestamp von einem Integer in ein Datum zu konvertieren. Ebenso war das suchen der Einträge einer Bikestation in einem zeitlichen Rahmen enorm unperformant. -* 60 Mio Datensätze -* Indexe für schnellere querries - * Indexe auf "computed values" -* SSD caching -* Vorberechnen der "Dashboard" Tabelle +Beide Probleme konnten durch spezifizierte Datenbankindexe gelöst werden. Jeder Dashboard-Endpoint hat seinen eigenen Index. + +Die Indexe sehen wie folgt aus: +```sql +CREATE INDEX IF NOT EXISTS "idx_date_of_start_date" ON usage_stats (date(start_date, 'unixepoch')) +CREATE INDEX IF NOT EXISTS "idx_end_station_id_date_of_start_date" ON "usage_stats" ("end_station_id" ASC, date(start_date, 'unixepoch')) +CREATE INDEX IF NOT EXISTS "idx_start_station_id_date_of_start_date" ON "usage_stats" ("start_station_id" ASC, date("start_date", 'unixepoch')) +``` +Jeder Index berechnet das Datum vor uns speichert es sozusagen als virtuelle Spalte in der Datenbank ab. Die zwei unteren betrachten hierzu noch die start- bzw. endstation. + +Dies hat die Performance enorm verbessert. + +| Abrufzeitraum | Durchschnittliche Zeit in Sekunden | +| --- | --- | +| ein Tag | 0.07 | +| eine Woche | 0.1 | +| zwei Wochen | 0.3 | +| ein Monat | 0.7 | +| drei Monate | 1.0 | +| ein Jahr | 2.25 | +| fünf Jahre (alles) | 20 | + +**Anmerkung:** Durch SSD Caching auf dem Server werden Abfragezeiten noch weiter reduziert. + +Alle Anfragen bis auf eine wurden dadurch performant. Bei der letzten handelt es sich um die Frage, welcher Analysezeitraum für eine Station verfügbar ist. Dies ist notwendig um die Grenzen des Date-Range-Pickers setzen zu können. +Gelöst wurde dieses Problem durch eine extra Tabelle welche die vorberechneten Werte für alle 840 Stationen beinhaltet. + +```sql +CREATE TABLE dashboard AS SELECT + b.id_num as id, + max(date(u.start_date, 'unixepoch')) AS max_end_date, + min(date(u.start_date, 'unixepoch')) AS max_start_date +FROM usage_stats u +JOIN bike_points b ON u.start_station_id = b.id_num +GROUP BY b.id_num +``` + +Die Berechnung dieser Tabelle dauert je nach Computer und Festplatte zwischen drei und zehn Minuten. Die Abfragedauer wird hierdurch um über 99 % reduziert, von etwa 20 Sekunden auf 10ms. + +Durch all diese Optimierungen wuchs die Datenbank von 6.2 Gigabyte auf fast 10 Gigabyte an! Ein einzelner Index hat hierbei über 1.2 Gigabyte. Die initiale Ladezeit des Dashbaord eines belibigen Bikepoints wurde hierdurch von etwa 35 Sekunden auf unter eine Sekunde reduziert! ## Dockerization * Unabhängigkeit von system requirements