Einleitung
Um nicht immer mit unserer produktiven DorisDB neue Sachen auszutesten, wollen wir uns ein kleines Testsystem erstellen. Dazu werden wir die uns schon bekannte DuckDB verwenden:
https://www.bi4you.org/artikel/duckdb-serverloses-in-memory-dbms/
Mit dieser sollten wir ein kleines unkompliziertes Testsystem aufbauen können.
Aktuelle DuckDB Version runterladen
Dazu verbinden wir uns per ssh auf unseren Raspberry Pi 5, legen einen neuen Ordner an und laden die aktuelle DuckDB Version herunter.
mkdir duckdb cd duckdb wget -c https://github.com/duckdb/duckdb/releases/download/v1.1.1/duckdb_cli-linux-aarch64.zip unzip duckdb_cli-linux-aarch64.zip
Und schon ist unsere Installation startklar.
DuckDB DB-Datei anlegen
Eine Persistente Datenbank legen wir an, indem wir beim Starten einen Dateinamen angeben:
./duckdb pv_anlage.duckdb
Tabellen anlegen
In unserer neuen Datenbank legen wir jetzt das Schema bme280 und die benötigten Tabellen pv_anlage, pv_anlage_stromtarife und jahreszeiten analog zu unseren MariaDB Tabellen an:
Schema anlegen
create schema bme280;
Tabelle pv_anlage
CREATE TABLE bme280.pv_anlage ( Datum_und_Uhrzeit DATE NULL, Gesamt_Erzeugung DECIMAL(10,4) NULL, Gesamt_Verbrauch DECIMAL(10,4) NULL, Eigenverbrauch DECIMAL(10,4) NULL, Energie_ins_Netz_eingespeist DECIMAL(10,4) NULL, Energie_vom_Netz_bezogen DECIMAL(10,4) NULL, PRIMARY KEY (Datum_und_Uhrzeit) );
Tabelle pv_anlage_stromtarife
CREATE TABLE bme280.pv_anlage_stromtarife ( Tarif VARCHAR(20) NULL, Datum_Von DATE NULL, Datum_Bis DATE NULL, Preis DECIMAL(10,6) NULL, EVN DECIMAL(10,6) NULL, Netznutzungsentgelt DECIMAL(10,6) NULL, Netzverlustentgelt DECIMAL(10,6) NULL, Elektrizitaetsabgabe DECIMAL(10,6) NULL, PRIMARY KEY (Tarif, Datum_Von, Datum_Bis) );
Tabelle jahrezeiten
CREATE TABLE bme280.jahreszeiten ( Jahreszeit VARCHAR(20) NULL, Beginn DATE NULL, Ende DATE NULL, PRIMARY KEY (Jahreszeit, Beginn, Ende) );
MariaDB Daten initial übernehmen
Mit dem Befehl ATTACH können wir unsere MariaDB in unsere neue Datenbank einhängen:
ATTACH 'host=192.168.42.10 user=bme280 password=bme280 port=3306 database=bme280' AS mysql_db (TYPE mysql_scanner, READ_ONLY);
Diesen ATTACH Befehl müssen wir jedes Mal neu eingeben, wenn wir den DuckDB Client beenden
Mit folgenden Befehlen können wir uns die Tabellen anzeigen lassen und somit testen, ob die Verbindung geklappt hat:
use mysql_db; show tables;
Als Liste bekommen wir unsere ganzen Tabellen und Views angezeigt – unsere Verbindung klappt also.
Unsere Daten können wir jetzt einfach mit inserts übernehmen:
insert into bme280.pv_anlage select * from mysql_db.pv_anlage; insert into bme280.pv_anlage_stromtarife select * from mysql_db.pv_anlage_stromtarife; insert into bme280.jahreszeiten select * from mysql_db.jahreszeiten;
View anlegen
Da wir die PV-Daten übernommen haben, können wir in unserer neuen Datenbank die pv_anlage_view anlegen.
Bei der Syntax müssen wir nur das date_format durch ein strftime ersetzen, den Rest können wir 1:1 übernehmen:
create view bme280.pv_anlage_view as ( select Datum_und_Uhrzeit as Datum, cast(YEAR(Datum_und_Uhrzeit) as varchar(4)) as Jahr, cast(case MONTHNAME(Datum_und_Uhrzeit) when 'January' then 'Jänner' when 'February' then 'Februar' when 'March' then 'März' when 'April' then 'April' when 'May' then 'Mai' when 'June' then 'Juni' when 'July' then 'Juli' when 'August' then 'August' when 'September' then 'September' when 'October' then 'Oktober' when 'November' then 'November' when 'December' then 'Dezember' Else 'Fehler' end as varchar(10)) as Monat, cast(case MONTHNAME(Datum_und_Uhrzeit) when 'January' then '01-Jänner' when 'February' then '02-Februar' when 'March' then '03-März' when 'April' then '04-April' when 'May' then '05-Mai' when 'June' then '06-Juni' when 'July' then '07-Juli' when 'August' then '08-August' when 'September' then '09-September' when 'October' then '10-Oktober' when 'November' then '11-November' when 'December' then '12-Dezember' Else 'Fehler' end as varchar(13)) as Monat_Sort, -- Astronomische Jahreszeiten -- j.Jahreszeit as Jahreszeit_Astronomisch, -- Meteorologische Jahreszeiten -- case when strftime(Datum_und_Uhrzeit,'%months-%days') between '03-01' and '05-31' then '01-Frühling' when strftime(Datum_und_Uhrzeit,'%months-%days') between '06-01' and '08-31' then '02-Sommer' when strftime(Datum_und_Uhrzeit,'%months-%days') between '09-01' and '11-30' then '03-Herbst' when strftime(Datum_und_Uhrzeit,'%months-%days') between '12-01' and '02-29' then '04-Winter' end as Jahreszeit_Meteorologisch, -- PV Daten round(Gesamt_Erzeugung/1000,2) as Produktion, round(Gesamt_Verbrauch/1000,2) as Gesamtverbrauch, round(Eigenverbrauch/1000,2) as Eigenverbrauch, round(Energie_ins_Netz_eingespeist/1000,2) as Netzeinspeisung, round(Energie_vom_Netz_bezogen/1000,2) as Netzbezug, round(Eigenverbrauch/Gesamt_Verbrauch*100,2) as Autarkie, round(Eigenverbrauch/Gesamt_Erzeugung*100,2) as Eigenverbrauchsquote, round(Energie_ins_Netz_eingespeist/Gesamt_Erzeugung*100,2) as Einspeisungsquote, round(Gesamt_Erzeugung/8000,2) as kWh_pro_kWp, round((Gesamt_Erzeugung/8000)/8.0*100,2) as Auslastung_pro_kWp, --Stromkosten/ersparnisse round(Eigenverbrauch/1000*b.Preis,6) as Stromkostenersparnis, round(Energie_vom_Netz_bezogen/1000*b.Preis,6) as Strombezugskosten, round(Energie_ins_Netz_eingespeist/1000*e.Preis,6) as Einspeisevergütung from bme280.pv_anlage p left outer join bme280.jahreszeiten j on p.Datum_und_Uhrzeit between j.Beginn and j.Ende left outer join bme280.pv_anlage_stromtarife b on p.Datum_und_Uhrzeit between b.Datum_Von and b.Datum_Bis and b.Tarif='Bezugstarif' left outer join bme280.pv_anlage_stromtarife e on p.Datum_und_Uhrzeit between e.Datum_Von and e.Datum_Bis and e.Tarif='Einspeisetarif' );
Unsere View können wir mit einem select testen:
select * from bme280.pv_anlage_view;
Die Daten sehen gut aus, unsere View ist somit startklar.
Incrementelle Datenübernahme
Für die Übernahme der neueren Daten erstellen wir uns ein Skript, dass uns die Daten von der MariaDB in unsere neue Datenbank bei Bedarf kopiert:
sync_from_mariadb.sh #!/bin/bash ./duckdb pv_anlage.duckdb -c "ATTACH 'host=192.168.42.10 user=bme280 password=bme280 port=3306 database=bme280' AS mysql_db (TYPE mysql_scanner, READ_ONLY); insert into bme280.pv_anlage (select m.* from mysql_db.pv_anlage m left outer join bme280.pv_anlage d on m.Datum_und_Uhrzeit=d.Datum_und_Uhrzeit where d.Datum_und_Uhrzeit is NULL);" ./duckdb pv_anlage.duckdb -c "ATTACH 'host=192.168.42.10 user=bme280 password=bme280 port=3306 database=bme280' AS mysql_db (TYPE mysql_scanner, READ_ONLY); insert into bme280.pv_anlage_stromtarife (select m.* from mysql_db.pv_anlage_stromtarife m left outer join bme280.pv_anlage_stromtarife d on m.Datum_Von=d.Datum_Von and m.Tarif=d.Tarif where m.Tarif='Bezugstarif' and d.Datum_Von is NULL);" ./duckdb pv_anlage.duckdb -c "ATTACH 'host=192.168.42.10 user=bme280 password=bme280 port=3306 database=bme280' AS mysql_db (TYPE mysql_scanner, READ_ONLY); insert into bme280.pv_anlage_stromtarife (select m.* from mysql_db.pv_anlage_stromtarife m left outer join bme280.pv_anlage_stromtarife d on m.Datum_Von=d.Datum_Von and m.Tarif=d.Tarif where m.Tarif='Einspeisetarif' and d.Datum_Von is NULL);"
DuckDB engine für Superset installieren
Um unsere DuckDB in Superset verwenden zu können, müssen wir zuerst die duckdb-engine installieren.
Dazu verbinden wir uns per ssh auf unseren Raspberry Pi 5 und aktivieren das Superset Environment mit
. superset/bin/activate
Danach können wir mit pip die Engine installieren
pip install duckdb-engine
Das Environment verlassen wir wieder mit
deactivate
Zum Schluss starten wir noch Superset neu
sudo systemctl restart superset
Datenbank in Superset verbinden
In Superset erstellen wir eine neue Datenbankverbindung, als Datenbank können wir jetzt DuckDB auswählen:
Als Name vergeben wir „bme280 (DuckDB)“, dann den Pfad zur unserer .duckdb Datei
Mit „Test Connection“ können wir noch überprüfen, ob wir uns verbinden können:
Im SQL Lab können wir jetzt unsere neue Datenbank auswählen und Abfragen darauf machen:
Fazit
Wir haben uns recht einfach und schnell ein kleines Testdatensystem aufgebaut und können unsere DuckDB nun in Superset für unsere Tests verwenden.
Sollten wir dann zufrieden mit einem Chart sein, können wir die Datasource auf unsere DorisDB ändern und in unsere produktiven Dashboards übernehmen.
Unsere Datenbank-Datei können wir zur Sicherung einfach wegkopieren – sollte etwas schief gehen, können wir sie einfach zurück kopieren und so unseren alten Stand wiederherstellen.