Hauptmenü

dbRep - export & purge

Begonnen von Frank_Huber, 22 Oktober 2019, 13:55:50

Vorheriges Thema - Nächstes Thema

Frank_Huber

Hallo Heiko,

Ich habe die Commandref und Wiki durchsucht, bin aber nicht fündig geworden.
Gibt es im dbRep die Möglichkeit eines "export & purge" ähnlich einer Archivierungsfunktion?
Also Alles was älter ist als z.B. 2 Jahre mit Ausnahme von Device XY exportieren und dann löschen.

Klar kann man es in zwei Schritten machen, es wäre aber eleganter in einem Schritt. ansonsten müsste man ja darauf achten dass sich die Ausführungen nicht überschneiden.

Danke & Grüße
Frank

DS_Starter

Hallo Frank,

eine integrierte Funktion, die beides in einem Lauf erledigt, ist noch nicht implementiert.
Aber es gibt natürlich Lösungen.

Eine Lösung wäre folgende.
Du definierst dir ein DbRep für den Export mit entsprechender Parametrisierung, Zeitabgrenzung, allowDeletion etc.
Zusätzlich setzt du dir das Attribut:


userExitFn delafterexport state:done


In die 99_myUtils stellst du die im Attr angegebene Funktion ein:


        sub delafterexport {
          my ($name,$reading,$value) = @_;
          my $hash = $defs{$name};

          fhem("set $name delEntries");
          Log3 $name, 1, "$name - start delete data after export. " ;

        return;
        }


Es passiert nun folgendes:
Du startest das DbRep mit "set ... exportToFile". Sobald der Export fehlerfrei durch ist (bei Fehler ist "state" nicht "done"), wird die Routine delafterexport (angegeben in userExitFn)  aufgerufen. Die Routine tut nichts anderes als das gleiche DbRep nun mit der Löschroutine aufzurufen und einen Eintrag ins Log zu schreiben.
Damit ist das Ziel erreicht.

Du solltest es aber erstmal testen und statt " fhem("set $name delEntries"); " zunächst "  fhem("set $name countEntries"); " ausprobieren.  ;)
Das Konstrukt kann man noch erweitern und ausbauen, z.B. zwei DbReps benutzen und sich am Ende eine Mail schicken lassen o.ä.

Grüße,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Frank_Huber

Morgen Heiko,

Danke für den Lösungsweg.
Wäre es nicht das gleiche wenn man den delEntries direkt in die userExitFn eintragen würde?
Wie verhält es sich mit dem "ExecAfterProc"? wird der dann in beiden Fällen ausgeführt?

Ich denke fast ich mach das über ein DOIF.
Uhrzeit und $mday --> reopen 3600 logdb auf allen Instanzen --> export starten
export:done --> löschen starten
löschen:done --> reopen auf allen Instanzen.
Das ganze dann über zwei getrennte dbRep.

Aber unabhängig davon hat es einen Haken, "älter 2 Jahre" arbeitet auch mit der Uhrzeit.
Der delEntries wird also ein paar Minuten später aufgerufen, genau um die Laufzeit des Exports.
Damit werden Daten gelöscht die nicht exportiert sind.
Ist in meinem Fall nicht so schlimm und ich baue das mal so ein, aber generell ist das natürlich unschön.
Bei einer langsamen Datenbank kann da ja durchaus ein größerer Zeitraum verloren gehen.

Grüße
Frank


DS_Starter

#3
Moin Frank,

delEntries direkt in die userExitFn klappt so nicht, weil delEntries ein FHEM Kommando ist aber in userExitFn eine Funktion eingetragen werden muss. Man braucht also einen kleinen Wrapper.
ExecAfterProc könnte man zwar benutzen, allerdings wird dieses Kommando ausgeführt egal ob das vorherige erfogreich beendet wurde oder nicht. Edit: Das bedeutet du musst dann Logik einbauen die entscheidet ob der vorangegangene Lauf erfolgreich war.

Dein Einwand mit der Relativzeit ist natürlich richtig. Man könnte mit einem festen Zeitpunkt "älter als" arbeiten, den man bei jedem Lauf operativ im Attr setzt.
Aber ich sehe schon, ich muss noch etwas auf meine ToDo setzen.  :)

Lg,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Frank_Huber

Wie gesagt, die paar Minuten "Verlust" stören mich nicht. Aber es mag ja andere Anwendungsfälle geben wo man nichts verlieren will.

Meiner Meinung nach könnte ein dbrep mit Monaten oder Jahren im "älter als" auch bis 00:00 arbeiten ohne die exakte Uhrzeit.
Damit wäre das Ergebnis vom Export und Delete das gleiche und man hätte immer ganze Tage exportiert.
Nur so als Idee, könnte ja ein Attribut sein oder eine Erweiterung "Y=2 fd" fd für FullDays.

DS_Starter

Deine Idee mit der Attributergänzung /Erweiterung "Y=2 fd" fd für FullDays finde ich gut.
Ich durchdenke das mal und setze es auf meine Todo Liste.
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Frank_Huber

Eines noch, die Idee mit dem state:done klappt auch nicht.
state ist  "Warning - export finished, but command message after export appeared"
ohne den reopen nach dem execute läöuft aber der zweite dbRep mit dem Count nicht an. --> "connection logdb to fhem is closed until 12:22:34 - countEntries postponed"
Ich werde mal versuchen den folgeschritt auf "done" oder "finished" zu triggern.

Gibt es ein Ergebis das "finished" enthält aber auf Fehler gelaufen ist?

DS_Starter

Nein, gibts nicht.
Du kannst ja auch done ersetzen durch einen etwas längeren String, z.b. "Warning - export finished, but".
Sollte auch funktionieren ...
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

DS_Starter

Übrigens musst du die MySqL bei diesen Operationen nicht zwangsläufig schließen. Diese DB kriegt das ohne Probleme auch parallel zum Logging hin. Das erspart dir bisschen Logikaufwand.
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Frank_Huber

Hab das jetzt über 3 dbRep Geräte und ein DOIF am laufen. (zum Test noch mit Count)
ja 1 dbRep zum exportieren, zählen (löschen) und vaccum.
das DOIF reagiert jeweils auf "done" oder "finished" und startet dann den nächsten Schritt.

läuft bis jetzt ganz gut, werd es mal noch ohne reopen testen.
Aber ich denke das reopen stört hier nicht wirklich.

DS_Starter

 Prima ... aber vacuum ? ... optimizeTables bei mysql ....
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Frank_Huber

Oh. das hab ich so noch im Kopf von früher unter SQlite.
Der Befehl läuft auch knapp 7 minuten.

Aber danke, bau ich um. :)

Frank_Huber

so, läuft erstmal alles wie es soll.
Wenn Du das vielleicht doch irgendwann einbaust bekomm ich das ja mit und kann es bei mir umbauen. Danke Heiko!
Bin jetzt btw von 22Mio auf 13,5 Mio Einträge runter.

verliere dann maximal einen Logcycle im Monat. Aber nur Raumtemperatur, Feuchte und Temperaturen der Heizung.

Falls es interessiert, hier die Definitionen:

DOIF:
defmod _logdb_bereinigen_1st DOIF ([01:00] and $mday==1)\
(set logdb_export_older_2years exportToFile)\
DOELSEIF ([logdb_export_older_2years:"done"] or [logdb_export_older_2years:"finished"])\
(set logdb_delete_older_2years delEntries)\
DOELSEIF ([logdb_delete_older_2years:"done"] or [logdb_delete_older_2years:"finished"])\
(set logdb_optimizeTables optimizeTables)\
DOELSEIF ([logdb_optimizeTables:"done"] or [logdb_optimizeTables:"finished"])
attr _logdb_bereinigen_1st DbLogExclude .*
attr _logdb_bereinigen_1st cmdState export|delete|optimize|finished
attr _logdb_bereinigen_1st group DB_cleanup_2y
attr _logdb_bereinigen_1st room SYSTEM
attr _logdb_bereinigen_1st verbose 0
attr _logdb_bereinigen_1st wait 0:5:5:0


EXPORT:
defmod logdb_export_older_2years DbRep logdb
attr logdb_export_older_2years DbLogExclude .*
attr logdb_export_older_2years aggregation month
attr logdb_export_older_2years device EXCLUDE=Verbrauch,Energiekosten
attr logdb_export_older_2years expimpfile /Q/backup/rpi/MySQL/older2y_%Y-%m-%d.csv
attr logdb_export_older_2years group DB_cleanup_2y
attr logdb_export_older_2years room SYSTEM
attr logdb_export_older_2years timeOlderThan y:2
attr logdb_export_older_2years verbose 0


DELETE:
defmod logdb_delete_older_2years DbRep logdb
attr logdb_delete_older_2years DbLogExclude .*
attr logdb_delete_older_2years aggregation month
attr logdb_delete_older_2years allowDeletion 1
attr logdb_delete_older_2years device EXCLUDE=Verbrauch,Energiekosten
attr logdb_delete_older_2years group DB_cleanup_2y
attr logdb_delete_older_2years room SYSTEM
attr logdb_delete_older_2years timeOlderThan y:2
attr logdb_delete_older_2years verbose 0


OPTIMIZE:
defmod logdb_optimizeTables DbRep logdb
attr logdb_optimizeTables DbLogExclude .*
attr logdb_optimizeTables group DB_cleanup_2y,DB_cleanup_3d
attr logdb_optimizeTables room SYSTEM
attr logdb_optimizeTables verbose 0


Rewe2000

Hallo,

vielen Dank für eure Lösung für das "Problem". Nach so einer Lösung hab ich auch schon viel gesucht. Ich werde dies mal bei mir einbauen, wenn ich wieder ein wenig Zeit habe.
Meine SQL Datenbank (Mariadb auf Raspi3) ist auch ständig am wachsen, ich habe die bisher immer händisch "verkleinert".

@Heiko
Wäre schön, wenn du das in nächster Zeit einbauen könntest, ich denke wir sind da nicht die einzigen, welche das brauchen können. Mit jeder User Meldung rutscht der Punkt hoffentlich ein wenig weiter nach oben, in deiner Todo Liste ;).

@Frank
Vielen Dank von meiner Seite, für das posten deines kompletten Codes.
ZitatBin jetzt btw von 22Mio auf 13,5 Mio Einträge runter.
Du hast die SQL Datenbank nicht auf einem Raspi laufen, bei meinen derzeit 2 Mio Datensätzen hab ich schon Bedenken, dass es irgendwann mal Probleme geben könnte.

Viele Grüße
Reinhard
Fhem 6.3 auf Raspberry Pi4 SSD mit Raspbian Bookworm, Homematic, Homematic IP, CCU3 mit RapberryMatic, WAGO 750-880, E3DC S10E Hauskraftwerk, E3DC Wallbox, my-PV AC ELWA-E Heizstab, Fritz!Box 7590, KIA Bluelinky

DS_Starter

Habe das ToDo mit einem Ausrufezeichen versehen  ;)
Aber wird vermutlich erst nach meinem Kurzurlaub.

Zitat... bei meinen derzeit 2 Mio Datensätzen hab ich schon Bedenken, dass es irgendwann mal Probleme geben könnte.
Brauchst du im Allgemeinen nicht haben. MySQL/MariaDB ist eine "erwachsene" Datenbank und wenn der Speicherplatz auf der Platte nicht aufgebraucht ist oder keine SQL-Statements abgesetzt werden deren Menge zu einem Overload deines RAM führen, läuft das. Wichtig ist natürlich das Vorhandensein des/der Indexe, sonst geht die Performance in den Keller !

Einer meiner Test-MariaDB hat gerade so 41Mio. Einträge und man merkt keinerlei Probleme beim Schreiben oder Plot-zeichnen.

Naja, aufräumen ist trotzdem nicht verkehrt. Man muß ja nichts mit sich rumschleppen was man nicht mehr braucht.  :)

Grüße,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter