NEWS
Zurücksetzen einzelner Datenpunkte im SQL-Adapter
-
@mike2712
wenn du so wenig Kenntnisse hast, dann würde ich ganz ehrlich raten auf das Löschen zu verzichten.
Besser die paar unnötigen Daten als dass etwas schief läuft...
Zum Löschen musst du im Skript die Konstante auf true setzen. Alles auf eigene Gefahr!Für Backup kannst du auch ioBroker backup Adapter verwenden
-
@andi2055 Danke, ja iobroker backup ist selbstverständlich vorhanden, es geht mir um die noch gültigen Einträge in der Datenbank (diese werden mit dem Adapter ja nicht gesichert), da habe ich kein Plan, ich wüsste auch nicht einmal wie ich es richtig händisch löschen müsste in der Datenbank, ich sehe die Datenpunkte, wenn ich einen Datenpunkt lösche, werden dann alle Daten zu diesem Datenpunkt gelöscht, aber händisch ist das sicher wie das aussieht auch sehr mühselig.
Was kann passieren wenn es mit dem scipt schief geht? Das ich die Daten verliere die in der Datenbank stehen, kann man in der Datenbank selbst ein komplette Update machen, habe versucht die Daten zu exportieren, aber das dauert ewig. -
@andi2055 sagte in Zurücksetzen einzelner Datenpunkte im SQL-Adapter:
ich habe dein Script ums Löschen von nicht mehr existierenden Datenpunkten erweitert.
So konnte ich bei mir über 1Mio überflüssige Datensätze löschen.
Vielleicht kann es jemand gebrauchen.
Verwendung auf eigene Gefahr! Vorher Backup anfertigenÖhm, Sehe ich das richtig das das Skript nur Daten von nicht mehr existierenden Datenpunkten löscht?
Ich würde auch gerne Datenpunkte löschen bei denen die SQL-Protokollierung deaktiviert wurde.Ich fang schon mal an zu suchen wie man das ermitteln kann ...
-
Und ich Antworte mir selbst:
Hier ist die Version die danach geht ob die Protokollierung per SQL aktiv ist.
Ist diese nicht (mehr) aktiv so taucht diese als zu löschen auf.
Gelöscht wird wie bisher auch wenn oben
const activate_delete = false;
auftrue
gesetzt wirdBenutzen auf eigene Gefahr, Verbesserungsvorschläge Willkommen.
Eventuell braucht das Skript langsam mal eine VersionierungHabe mal einen kleinen Header dazu gesetzt mit den Änderungen// SQL_Delete_Dead_Objects // V0.3 // // Changelog: // ---------- // 10.08.2019 V0.1 Scrounger erste Version welche nicht mehr existierende Datenpunkte anzeigt https://forum.iobroker.net/post/289821 // 03.05.2022 V0.2 andi2055 erweitert das die Daten auch aus der Datenbank gelöscht werden https://forum.iobroker.net/post/798291 // 01.02.2023 V0.3 BananaJoe umgestellt das nun Datenpunkte ohne SQL-Protokollierung gefunden werden https://forum.iobroker.net/post/939101 async function wartung() { try { // Hier das löschen einschalten! Sonst nur Trocken-Test const activate_delete = false; // Alle Datenpunkte holen bei welchen die SQL-Protokollierung aktiv ist: let datapointsActiveArray = new Array(); let datapointsActiceStrings = ""; await sendTo('sql.0', 'getEnabledDPs', {}, function (result) { Object.entries(result).forEach((entry) => { const [key, value] = entry; // console.log(`${key}`); datapointsActiceStrings = datapointsActiceStrings + `${key}` + ";"; }); //console.log(datapointsActiceStrings); datapointsActiveArray = datapointsActiceStrings.split(';'); }); // alle Datenpunkte aus Db holen let datapoints = await getQueryResult(`SELECT * FROM iobroker.datapoints`); if (datapoints) { let count = 0; let sum = 0; // Datenpunkte durchlaufen for (const datapoint of datapoints) { // prüfen ob kein Objekt in ioBroker existiert // if (!getObject(datapoint.name)) { // prüfen ob SQL-Protokollierung nicht aktiv ist if (!datapointsActiveArray.includes(datapoint.name)) { count++; // Daten des Datenpunktes in Tabelle 'ts_bool' zählen let countBool = 0; let booleanTableItems = await getQueryResult(`SELECT * FROM iobroker.ts_bool WHERE id = ${datapoint.id}`); if (booleanTableItems && Object.keys(booleanTableItems).length > 0) { countBool = Object.keys(booleanTableItems).length; if (activate_delete) { sendTo('sql.0', 'query', `DELETE FROM iobroker.ts_bool WHERE id = ${datapoint.id}`, function (result) { if (result.error) { console.error(result.error); } else { // show result console.log('Rows: ' + JSON.stringify(result.result)); } }); } } // Daten des Datenpunktes in Tabelle 'ts_number' zählen let countNumber = 0; let numberTableItems = await getQueryResult(`SELECT * FROM iobroker.ts_number WHERE id = ${datapoint.id}`); if (numberTableItems && Object.keys(numberTableItems).length > 0) { countNumber = Object.keys(numberTableItems).length; if (activate_delete) { sendTo('sql.0', 'query', `DELETE FROM iobroker.ts_number WHERE id = ${datapoint.id}`, function (result) { if (result.error) { console.error(result.error); } else { // show result console.log('Rows: ' + JSON.stringify(result.result)); } }); } } // Daten des Datenpunktes in Tabelle 'ts_string' zählen let countString = 0; let stringTableItems = await getQueryResult(`SELECT * FROM iobroker.ts_string WHERE id = ${datapoint.id}`); if (stringTableItems && Object.keys(stringTableItems).length > 0) { countString = Object.keys(stringTableItems).length; if (activate_delete) { sendTo('sql.0', 'query', `DELETE FROM iobroker.ts_string WHERE id = ${datapoint.id}`, function (result) { if (result.error) { console.error(result.error); } else { // show result console.log('Rows: ' + JSON.stringify(result.result)); } }); } } if (activate_delete) { sendTo('sql.0', 'query', `DELETE FROM iobroker.datapoints WHERE id = ${datapoint.id}`, function (result) { if (result.error) { console.error(result.error); } else { // show result console.log('Rows: ' + JSON.stringify(result.result)); } }); } console.warn(`DB id: ${datapoint.id} (type: ${datapoint.type}) -> number: ${countNumber}, string: ${countString}, bool: ${countBool} | ioBroker id: '${datapoint.name}'`); sum = sum + countBool + countNumber + countString; } } console.warn(`${count} Objects found, that not exist anymore in ioBroker, sum of items in tables: ${sum.toLocaleString().replace(/,/g, ".")}`); } } catch (err) { console.error(`[wartung] error: ${err.message}`); console.error(`[wartung] stack: ${err.stack}`); } } async function getQueryResult(query) { return new Promise((resolve, reject) => { sendTo('sql.0', 'query', query, function (result) { if (!result.error) { resolve(result.result); } else { resolve(null); } }); }); } wartung();
-
@bananajoe
Habe das Script als js eingefügt und gestartet.
Es tut sich gar nichts; absolut nichts im log.Muss man da irgendwas beachten ?
-
@bahnuhr also nicht mal einen Fehler oder so?
da sollte unten doch stehen das er das Skript gestartet hat - und dann kommt nichts?
Die Zusammenfassung sollte auf jeden Fall kommen (und wenn die 0 ist).Sind Log-Ausgaben als Warnung.
-
Wenn ich das Script starte kommt unten im log:
Sonst nix.
manches ist auch rot unterstrichen:
komisch
-
@bananajoe
Und bei sql ist folgendes in der config:
-
@bahnuhr wie heisst denn deine Instanz?
sql.0
? Laut deinem Screehshot schon.
Das steht nämlich so fest verdrahtet im Skript. (noch)
Mit SQLite habe ich das auch nicht getestet, spricht aber eigentlich nichts dagegen das es funktionieren sollte.sonst nimm mal in Zeile 23 die
//
vorne weg, dann müsste er die im Log unten die ganzen Datenpunkte auflistenNachtrag: Die letzte Zeile hast du mit kopiert, oder?
wartung();
Die ruft die Funktion ja erst auf
-
@bananajoe sagte in Zurücksetzen einzelner Datenpunkte im SQL-Adapter:
sql.0 ?
@bananajoe sagte in Zurücksetzen einzelner Datenpunkte im SQL-Adapter:
Zeile 23 die //
Hatte ich schon; alle DP werden im log aufgelistet.
Es kommen da schon ca. 100 (nicht gezählt)@bananajoe sagte in Zurücksetzen einzelner Datenpunkte im SQL-Adapter:
Nachtrag: Die letzte Zeile hast du mit kopiert, oder?
Na sicher, Script startet ja auch.
Und die DP werden im log wenn Zeile 23 aktiv auch aufgelistet.
Und wenn Zeile 26 (auc log) aktiv ist, das funktioniert auch.Ich glaube es liegt an dieser Zuweisung:
let datapoints = await getQueryResult(`SELECT * FROM iobroker.datapoints`);
Das scheint nicht zu klappen
-
so ich habs:
Die Zeile 31 läuft nicht:
falsch ist:
let datapoints = await getQueryResult(SELECT * FROM iobroker.datapoints
);richtig ist:
let datapoints = await getQueryResult(SELECT * FROM datapoints
);Jetzt kommt bei mir im log auch sowas:
javascript.0 2023-02-01 21:12:53.124 warn script.js.Scripte.test9: 15 Objects found, that not exist anymore in ioBroker, sum of items in tables: 0 javascript.0 2023-02-01 21:12:53.104 warn script.js.Scripte.test9: DB id: 280 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'hm-rpc.0.OEQ2092890.4.ACTUAL_TEMPERATURE' javascript.0 2023-02-01 21:12:53.078 warn script.js.Scripte.test9: DB id: 242 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'zigbee.0.00124b00246e6a5d.co2' javascript.0 2023-02-01 21:12:53.054 warn script.js.Scripte.test9: DB id: 241 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'javascript.0.System.Sonstige.Tablet_Surface_Akku' javascript.0 2023-02-01 21:12:53.031 warn script.js.Scripte.test9: DB id: 228 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'alias.0.HM.Sonstige.Duty_cycle.Wert' javascript.0 2023-02-01 21:12:53.008 warn script.js.Scripte.test9: DB id: 227 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'modbus.0.inputRegisters.1.30053_Total_system_power' javascript.0 2023-02-01 21:12:52.970 warn script.js.Scripte.test9: DB id: 226 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'modbus.0.inputRegisters.1.30017_Phase_3_active_power' javascript.0 2023-02-01 21:12:52.898 warn script.js.Scripte.test9: DB id: 225 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'modbus.0.inputRegisters.1.30015_Phase_2_active_power' javascript.0 2023-02-01 21:12:52.868 warn script.js.Scripte.test9: DB id: 224 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'modbus.0.inputRegisters.1.30013_Phase_1_active_power' javascript.0 2023-02-01 21:12:52.840 warn script.js.Scripte.test9: DB id: 223 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'libre.0.168e5f9c-3b6c-11ed-b7a7-0242ac110008.graph.connection.glucoseMeasurement.Value' javascript.0 2023-02-01 21:12:52.813 warn script.js.Scripte.test9: DB id: 133 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'hm-rega.0.PEQ1453161.0.DUTY_CYCLE' javascript.0 2023-02-01 21:12:52.788 warn script.js.Scripte.test9: DB id: 128 (type: 2) -> number: 0, string: 0, bool: 0 | ioBroker id: 'hm-rpc.0.LEQ0425576.1.STATE' javascript.0 2023-02-01 21:12:52.758 warn script.js.Scripte.test9: DB id: 126 (type: 2) -> number: 0, string: 0, bool: 0 | ioBroker id: 'hm-rpc.0.MEQ0273625.1.STATE' javascript.0 2023-02-01 21:12:52.731 warn script.js.Scripte.test9: DB id: 124 (type: 2) -> number: 0, string: 0, bool: 0 | ioBroker id: 'hm-rpc.0.OEQ0928918.1.STATE' javascript.0 2023-02-01 21:12:52.707 warn script.js.Scripte.test9: DB id: 119 (type: 2) -> number: 0, string: 0, bool: 0 | ioBroker id: 'hm-rpc.0.LEQ0031112.1.MOTION' javascript.0 2023-02-01 21:12:52.676 warn script.js.Scripte.test9: DB id: 90 (type: 0) -> number: 0, string: 0, bool: 0 | ioBroker id: 'javascript.0.System.Sonstige.Tablet_Wz_Akku'
-
@bahnuhr ahh, da liegt der Hase im Pfeffer - deine Datenbank heißt nicht "iobroker".
Zufällig hieß die bei mir auch so.
iobroker.datapoints
ist die Tabelledatapoints
aus der Datenbankiobroker
Also 2 Dinge sollte man noch als Parameter an den Anfang setzen, die Instanz und den Namen der Datenbank - wobei der auch vermutlich weggelassen werden könnte da diese ja schon im SQL-Adapter festgelegt ist.
-
@bananajoe & @Scrounger @andi2055
Lieben Dank, wie lange suche ich schon eine Lösung meine Mio von Leichen los zu werden. Aber irgendwas mache ich falsch mit der Nutzung des Scripts.
- JS Adapter öffnen
- neues JS anlegen
- Script von bananajoe einfügen, speichern
- Script oben mit der Pfeiltaste starten und warten
.
.
. - nix passiert
- im Log steht nach wie vor:
javascript.0 2023-02-02 00:00:31.728 info script.js.010_Testen.SQL_Datenpunkte_löschen: registered 0 subscriptions, 0 schedules, 0 messages, 0 logs and 0 file subscriptions javascript.0 2023-02-02 00:00:31.703 info Start javascript script.js.010_Testen.SQL_Datenpunkte_löschen javascript.0 2023-02-02 00:00:31.656 info Stop script script.js.010_Testen.SQL_Datenpunkte_löschen
Sollte da irgendwo irgendetwas passieren. Ja, ich will vorab einen "Trocken-Test" machen um dann letztendlich den Schritt wagen.
-
Hier mal Version V0.4.
In dieser kannst du oben auch den Datenbank-Namen festlegen.
Im Quelltext war der bisher fest verdrahtet aufiobroker
gesetzt, deine heißt aber z.B.ioBroker
Passe das an und teste noch einmal.// SQL_Delete_Dead_Objects // V0.3 // // Changelog: // ---------- // 10.08.2019 V0.1 Scrounger erste Version welche nicht mehr existierende Datenpunkte anzeigt https://forum.iobroker.net/post/289821 // 03.05.2022 V0.2 andi2055 erweitert das die Daten auch aus der Datenbank gelöscht werden https://forum.iobroker.net/post/798291 // 01.02.2023 V0.3 BananaJoe umgestellt das nun Datenpunkte ohne SQL-Protokollierung gefunden werden https://forum.iobroker.net/post/939101 // 02.02.2023 V0.4 BananaJoe SQL-Instanz Konfigurierbar / Datenbankname konfigurierbar // Einstellungen: // Hier das löschen einschalten! false = nur anzeigen / true = anzeigen und wirklich löschen const activate_delete = false; // Name der SQL-Instanz, normalerweiser sql.0 const sql_instance = 'sql.0'; // Name der SQL-Datenbank - Groß und Kleinschreibung beachten! const sql_dbname = 'iobroker'; // Funktion zum Suchen und Löschen async function wartung() { try { // Alle Datenpunkte holen bei welchen die SQL-Protokollierung aktiv ist: let datapointsActiveArray = new Array(); let datapointsActiceStrings = ""; await sendTo(sql_instance, 'getEnabledDPs', {}, function (result) { Object.entries(result).forEach((entry) => { const [key, value] = entry; //console.log(`${key}`); datapointsActiceStrings = datapointsActiceStrings + `${key}` + ";"; }); //console.log(datapointsActiceStrings); datapointsActiveArray = datapointsActiceStrings.split(';'); }); // alle Datenpunkte aus Db holen let datapoints = await getQueryResult(`SELECT * FROM ${sql_dbname}.datapoints`); if (datapoints) { let count = 0; let sum = 0; // Datenpunkte durchlaufen for (const datapoint of datapoints) { // prüfen ob kein Objekt in ioBroker existiert // if (!getObject(datapoint.name)) { // prüfen ob SQL-Protokollierung nicht aktiv ist if (!datapointsActiveArray.includes(datapoint.name)) { count++; // Daten des Datenpunktes in Tabelle 'ts_bool' zählen let countBool = 0; let booleanTableItems = await getQueryResult(`SELECT * FROM ${sql_dbname}.ts_bool WHERE id = ${datapoint.id}`); if (booleanTableItems && Object.keys(booleanTableItems).length > 0) { countBool = Object.keys(booleanTableItems).length; if (activate_delete) { sendTo(sql_instance, 'query', `DELETE FROM ${sql_dbname}.ts_bool WHERE id = ${datapoint.id}`, function (result) { if (result.error) { console.error(result.error); } else { // show result console.log('Rows: ' + JSON.stringify(result.result)); } }); } } // Daten des Datenpunktes in Tabelle 'ts_number' zählen let countNumber = 0; let numberTableItems = await getQueryResult(`SELECT * FROM ${sql_dbname}.ts_number WHERE id = ${datapoint.id}`); if (numberTableItems && Object.keys(numberTableItems).length > 0) { countNumber = Object.keys(numberTableItems).length; if (activate_delete) { sendTo(sql_instance, 'query', `DELETE FROM ${sql_dbname}.ts_number WHERE id = ${datapoint.id}`, function (result) { if (result.error) { console.error(result.error); } else { // show result console.log('Rows: ' + JSON.stringify(result.result)); } }); } } // Daten des Datenpunktes in Tabelle 'ts_string' zählen let countString = 0; let stringTableItems = await getQueryResult(`SELECT * FROM ${sql_dbname}.ts_string WHERE id = ${datapoint.id}`); if (stringTableItems && Object.keys(stringTableItems).length > 0) { countString = Object.keys(stringTableItems).length; if (activate_delete) { sendTo(sql_instance, 'query', `DELETE FROM ${sql_dbname}.ts_string WHERE id = ${datapoint.id}`, function (result) { if (result.error) { console.error(result.error); } else { // show result console.log('Rows: ' + JSON.stringify(result.result)); } }); } } if (activate_delete) { sendTo(sql_instance, 'query', `DELETE FROM ${sql_dbname}.datapoints WHERE id = ${datapoint.id}`, function (result) { if (result.error) { console.error(result.error); } else { // show result console.log('Rows: ' + JSON.stringify(result.result)); } }); } console.warn(`DB id: ${datapoint.id} (type: ${datapoint.type}) -> number: ${countNumber}, string: ${countString}, bool: ${countBool} | ioBroker id: '${datapoint.name}'`); sum = sum + countBool + countNumber + countString; } } console.warn(`${count} Objects found, that not exist anymore in ioBroker, sum of items in tables: ${sum.toLocaleString().replace(/,/g, ".")}`); } } catch (err) { console.error(`[wartung] error: ${err.message}`); console.error(`[wartung] stack: ${err.stack}`); } } async function getQueryResult(query) { return new Promise((resolve, reject) => { sendTo(sql_instance, 'query', query, function (result) { if (!result.error) { resolve(result.result); } else { resolve(null); } }); }); } wartung();
In der nächsten Version könnte man eine Meldung ergänzen wenn er keine Datenpunkte gefunden hat - dann wäre vermutlich die Instanz oder der Name der Datenbank falsch.
Eventuell kann man sich den Namen der Datenbank auch vom Adapter holen. Den Namen einfach überall entfernen hatte nicht zum Erfolg geführt. -
@bananajoe Danke!
Das mit dem Case Sensitive hatte ich schon entdeckt und manuell alles in der v0.3 abgeändert. Lief dann auch wirklich los und es kamen die orangenen Zeilen im Log. Allerdings scheint für so eine Rechenleistung mein System zu brustschwach zu sein. Bin gerade dabei, mein System wieder hoch zu kriegen. Ist einfach abgeschmirrt.
-
@metaxa nicht abgeschmiert ... Geduld. Habe ich eben sogar auf meinem Hochleistungssystem gehabt. Sind ggf. halt hunderttausende vorn Abfragen.
Eventuell muss da halt noch eine Bremse rein. Und Statusanzeigen.
-
@bananajoe sagte in Zurücksetzen einzelner Datenpunkte im SQL-Adapter:
Eventuell muss da halt noch eine Bremse rein. Und Statusanzeigen.
Ich denke beides wäre sehr hilfreich, alleine das Backup der SQL Datenbank ist bei mir ~500MB groß. Bei mir kommen im Log ca. 84 Warnmeldungen, spätestens danach tut sich nix mehr und der Admin ist nicht mehr erreichbar. Ich habe das Gefühl, dass der JS Adapter neu startet, da plötzlich im Log sichtbar jedes Skript neu initialisiert wird.
Werde das System jetzt neu starten, danach nochmals dein Skript starten traue ich mich eigentlich nicht wirklich.
-
@metaxa sagte in Zurücksetzen einzelner Datenpunkte im SQL-Adapter:
Werde das System jetzt neu starten, danach nochmals dein Skript starten traue ich mich eigentlich nicht wirklich.
eventuell musst den Javascript-adapter vorher deaktivieren - wenn der startet, startet der auch alle skripte die gestartet waren. könnte auch über den Objektebaum gehen, weis aber gerade nicht wie.
Also keine Panik, ggf. warten, warten, warten
-
@bananajoe sagte in Zurücksetzen einzelner Datenpunkte im SQL-Adapter:
eventuell musst den Javascript-adapter vorher deaktivieren
Wie meinst du das? Ich kann dein Skript ja nur starten, wenn er läuft. Laut meinen Beobachtungen hat mein JS-Adapter inmitten des laufenden Prozesses deines Skripts neugestartet.
-
@metaxa ok ... wenn es viele sind braucht es wohl eher einen Limiter "Datenpunkte pro Start", also das er nicht alle Datenpunkte abarbeitet sondern nur Anzahl X pro Start.
Ich habe gerade mit einer Bremse experimentiert. Er sucht die Datenpunkte ohne Fahrschein und fragt dann die Wert die vorliegen ab um eine Zahl zu erhalten.
Mein einer Temperatursensor schickt z.B. alle 5 Sekunden einen Wert (war mir erst hierbei aufgefallen), das waren es dann über 200.000 Werte.
In diese Abfrage kann ich nicht pausieren (ok, ich könnte die limitieren, dann wird es aber komplizierter, dann bräuchte es noch einmal eine schleife drumherum um dann alle Werte zu verarbeiten)
Zwischen den Datenpunkten kann ich pausieren.
Bei zu vielen Datensätzen könnte der RAM ausgehen ... wenn da z.B. 500.000 Stück kommen.
Also vermutlich läuft es doch auf "maximal 50.000 Datensätze pro Runde) oder so. Also statt 500.000 zu verarbeiten immer nur "die ersten 50.000, dann die nächsten 50.000) usw.Ich bin jetzt kein SQL Profi, ich kann nur gut googeln, ich schau mal was ich da finde.