Update Umsetzung

Marcel Schwarz 2021-01-17 22:11:13 +00:00
parent f5c29789e8
commit 1a64499a77

@ -140,23 +140,62 @@ Der Aufruf von `api_database.get_all_accidents()` ist nun nur noch eine reine de
### Probleme ### 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: 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 | Abrufzeitraum | Durchschnittliche Zeit in Sekunden |
* Abruf von **einer Woche:** ~1.25s | --- | --- |
* Abruf von **zwei Wochen:** ~12s | ein Tag | 0.3 |
* Abruf von **einem Monat:** ~90s | eine Woche | 1.25 |
* Abruf von **drei Monaten:** ~7min | zwei Wochen | 12 |
* Abruf von **einem Jahr:** Nicht möglich! | 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. Das würde bedeuten, dass wir nur etwa 10% unseres Datensatzes nutzen könnten.
## Performance ## 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 Beide Probleme konnten durch spezifizierte Datenbankindexe gelöst werden. Jeder Dashboard-Endpoint hat seinen eigenen Index.
* Indexe für schnellere querries
* Indexe auf "computed values" Die Indexe sehen wie folgt aus:
* SSD caching ```sql
* Vorberechnen der "Dashboard" Tabelle 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 ## Dockerization
* Unabhängigkeit von system requirements * Unabhängigkeit von system requirements