Datenlogging mit PostgreSQL

Hallo
Ich finde es echt toll dass Ihr euch die Mühe macht eine Datenbank zu erklären.
Leider klappt es bei mir noch nicht wie es soll.
Ich habe eigentlich alles gemacht wie beschrieben.

Nur wo soll ich dies ausführen und was muss ich dann für Dateien finden?
<? phpinfo();?>

Ich habe mal das Skript so eingefügt wie beschrieben und die Datenbank installiert und konfiguriert. Ich weiß leider nicht welche IP ich angeben soll .
Wie Ihr auf dem Bild erkennen könnt habe ich es mit der vom Rechner versucht.
Bitte um Hilfe Fränki

Ich weiß leider nicht welche IP ich angeben soll .

Die IP des Rechners wo die Datenbank drauf läuft.

Die beiden Dateien musst Du dort hin kopieren wie angegeben.!

Hallo Rainer
Das ich es als Laie geschafft habe, alles so funktioniert wie du es beschrieben hast grenzt an ein Wunder oder besser gesagt Du hast deine Aufge ganz toll erledigt.
Danke für deine Mühe.
Gruß Fränki

P.s. Kannst du mir das Skript für die Variabelübernahme zusenden

Hallo
Mit der Gefahr dass ich gleich fertig gemacht werde da ich eine Frage stelle die jeder eigentlich beantworten kann.

Ist es problemlos möglich das Skript auf eine andere Datenbank umzuschreiben? Ich habe leider keine Ahnung von diesen Dingen und bin auf andere angewiesen.
Ich habe ein Ziel dass meine Investition irgend wann mal so fruchtet dass ich zufrieden bin.

Ich hoffe der Spruch gilt auch hier dass es keine dumme Fragen gibt sondern nur dumme Antworten.
Mein Wunsch wäre es dass es mal so aussieht wie in diesem Projekt.
http://www.ip-symcon.de/forum/f16/verbrauchsdaten-visualisieren-ipsymcon-6354/

Danke mit der Bitte um Hilfe
Fränki

script-3.txt (944 Bytes)

Hallo Fränki,

sicher ist das möglich. Du musst nur die entsprechende Tabelle in deiner Datenbank anlegen. Das Script was Du angehängt hast, schreibt nur die Daten in die Tabelle.

Hallo
Danke für deine Antwort.
Ich habe eine Datenbank angelegt und versuche nun eine Tabelle mit CID , Float, anzulegen.
Leider finde ich bei Dateityp meiner Tabellenspalte den Wert " FLOAT" nicht.
Heißt dieser dort anders?
Danke Fränki

Du könntest z.B. REAL verwenden wenn Du bei Postgre bist.

Rainer, diese Anleitung ist „AMAZING“! In kurzer Zeit konnte ich endlich mein SQL-Logging aktivieren! Danke!!!

Nun frage ich mich, was ich mit den alten Beständen aus logging.db machen soll. Da Du praktisch an alles gedacht hast, kann ich nicht der Versuchung widerstehen und fragen: „Hast Du zufällig auch noch einen Script, der durch die alten Datenbestände von logging.db loopt, die geloggten Variablen holt, und nach Postgres migriert???“ Vielen Dank im Voraus für Deine geschätzte Hilfe!

Dafür hab ich kein Script. Das wird auch mit einem Script nicht so einfach gehen. Je nachdem wie deine Struktur ist wird es ohne Handarbeit warscheinlich nicht gehen.
Diese Arbeit hab ich mir nicht gemacht, war damals alles Neuanlage.

Danke trotzdem. Wenn ich mir die Möglichkeiten von Postgres anschaue, so denke ich, dass sich die Migration auf jeden Fall lohnt!

So, nun habe ich den Sprung ins Postgres geschafft, und bin ganz happy damit.

Mir stellen sich aber noch einige Fragen zur Architektur der externen Speicherung. LoggingDb speichert folgende Werte:

[ul]
[li]timestamp INTEGER ,
[/li][li]varid INTEGER ,
[/li][li]counter INTEGER ,
[/li][li]lasttime INTEGER ,
[/li][li]duration INTEGER ,
[/li][li]status INTEGER ,
[/li][li]value REAL
[/li][/ul]

Mir ist unklar, ob es sich lohnt, alle diese Felder auch in Postgres abzubilden. Der potentielle Vorteil wäre die Kompatibilität, aber ist das überhaupt wichtig? Ich finde, dass man duration auf jeden Fall lassen kann, denn duration=lasttime-timestamp. Aber was ist mit lasttime, counter, und status? Es ist mir essentiell, jetzt alles richtig zu machen - denn es gibt kein zurück und eine schlechte Struktur wird mich über Jahre verfolgen!

Und noch: ist es empfehlenswert, weitere fields zu speichern? ParentName wäre für mich z.B. sinnvoll, am besten rekursiv als „parentName/parentName/parentName/varName“. Was sind denn Eure Erfahrungen?

Das wirst Du alleine entscheiden müssen. Wichtig ist, dass Du eine eindeutige ID vergibst. Ansonsten, VarID, Value und Timestamp. Nice to have, Suffix, Varname.

Alles andere was Du brauchst, kannst Du intern mit der Datenbank machen aber wie schon gesagt, musst Du selbst entscheiden.

Ich persönlich schreibe für jede Variable eine Tabelle. Ich hatte ein halbes Jahr 2 Datenbanken parallel laufen, eine mit allen Variablen in einer Tabelle und eine mit einer Tabelle je Variable. Ergebnis, letzteres ist um ca Faktor 5 schneller. Ist schon ein Unterschied ob 20000000 oder 200000 Datensätze durchsucht werden müssen.

Danke Rainer. Das ist eine sehr interessante, fast schon philosophische Diskussion! Auf die Idee, eine Tabelle pro Variable anzulegen, wäre ich nicht gekommen - aber eine Beschleunigung um 5x ist wohl ein sehr starkes Argument!

Extrem viele Tabellen wären aber mir zu unübersichtlich. Aber es muss ja nicht alles in einer einzigen Tabelle sein. Vielleicht ist schon was gewonnen, wenn ich getrennteTabellen für String, Integer, Real, und Boolean-Variablen anlege. Diese können dann jeweils mit optimierten Algorithmen abgesucht werden, was vielleicht etwas Zeit spart.

Was varName etc. betrifft, diese Angaben sollten wahrscheinlich am besten in einer relational verknüften Tabelle stehen. Sonst ist bei jeder Aenderung des von varName die relationale Integrität hinüber.

Es wäre natürlich ideal, wenn sich all die SQL-Cracks im Forum auf einen gemeinsame „halb-offizielle“ Minimaldefinition des logging einigen würden, so dass wir alle gemeinsam wiederverwertbare Logik darauf aubauen könnten.

also habe ich einen kleinen Script produziert, der alle IPS-Objekte in eine PG-Tabelle hinterlegt, zur relationalen Verwendung mit den Value-Tabellen.


<?php
$IpsObjectList = IPS_GetObjectList();
$CountIpsObjects = count($IpsObjectList);
echo $CountIpsObjects. " ips objects"."<br>";
//print_r($IpsObjectList);

$dbconn = pg_connect("host=localhost port=5432 dbname=IpsLogging user=IPS password=ips") or die ('Verbindungsaufbau fehlgeschlagen: ' . pg_last_error());
echo $dbconn . "<br>";
if ($dbconn==0) {die ("no odbc connection");} 

pg_query($dbconn, "DROP TABLE IpsObjects;");

$createTable = "    CREATE TABLE IpsObjects (
					CHILDRENIDS TEXT, 
					HASCHILDREN BOOLEAN, 
					ISPERSISTENT BOOLEAN, 
					OBJECTICON TEXT, 
					OBJECTID INTEGER UNIQUE, 
					OBJECTIDENT TEXT, 
					OBJECTINFO TEXT, 
					OBJECTISHIDDEN BOOLEAN, 
					OBJECTISREADONLY BOOLEAN, 
					OBJECTNAME TEXT, 
					OBJECTPOSITION TEXT, 
					OBJECTSUMMARY TEXT, 
					OBJECTTYPE INTEGER, 
					PARENTID INTEGER,
					ID SERIAL, 
                    PRIMARY KEY(ID)
                    );";
pg_query($dbconn, $createTable);



$SqlExecuteString ="";
$SqlInsertString = "ChildrenIDs, HasChildren, IsPersistent, ObjectIcon, ObjectID, ObjectIdent, ObjectInfo, ObjectIsHidden, ObjectIsReadOnly, ObjectName, ObjectPosition, ObjectSummary, ObjectType, ParentID";

//$SqlValueString = "0,0,0,0,0,0,0,0,0,0, 0,0,0,0";


foreach ($IpsObjectList as $key1 => $value1) 
	{
    echo "[$key1] => $value1"."<br>";
	$IpsObject=IPS_GetObject($value1);
		(string)$ChildrenIDs = utf8_encode(SqlNull(implode(",",$IpsObject['ChildrenIDs'])));
		(bool)$HasChildren = SqlNull($IpsObject['HasChildren']);
		(bool)$IsPersistent= $IpsObject['IsPersistent'];
		(string)$ObjectIcon=utf8_encode(SqlNull($IpsObject['ObjectIcon']));
		(int)$ObjectID=SqlNull($IpsObject['ObjectID']);
		(string)$ObjectIdent=utf8_encode(SqlNull($IpsObject['ObjectIdent']));
		(string)$ObjectInfo=utf8_encode(SqlNull($IpsObject['ObjectInfo']));
		(bool)$ObjectIsHidden= SqlNull($IpsObject['ObjectIsHidden']);
		(bool)$ObjectIsReadOnly= SqlNull($IpsObject['ObjectIsReadOnly']);
		(string)$ObjectName=utf8_encode($IpsObject['ObjectName']);
		(string)$ObjectPosition=utf8_encode(SqlNull($IpsObject['ObjectPosition']));
		(string)$ObjectSummary=utf8_encode(SqlNull($IpsObject['ObjectSummary']));
		(int)$ObjectType=SqlNull($IpsObject['ObjectType']);
		(int)$ParentID=SqlNull($IpsObject['ParentID']);
$SqlValueString = 
  "'".$ChildrenIDs."',". 
  $HasChildren . ",". 
  $IsPersistent . ",". 
  "'" .$ObjectIcon."'" . ",". 
  $ObjectID . ",". 
  "'" .$ObjectIdent."'" . ",". 
  "'".$ObjectInfo."'". ",". 
  $ObjectIsHidden . ",". 
  $ObjectIsReadOnly . ",". 
  "'".$ObjectName. "'".",". 
  $ObjectPosition . ",". 
  "'".$ObjectSummary. "'".",". 
  $ObjectType . ",". 
  $ParentID;

$SqlExecuteString = "INSERT INTO IpsObjects ($SqlInsertString) VALUES ($SqlValueString);".chr(13);
echo $SqlExecuteString;
$QueryResult = pg_query($dbconn,  $SqlExecuteString);
if (!$QueryResult) 
{
//  echo "A Postgres error occured:". pg_last_error();		
	}

}
pg_close($dbconn);


//----------------------------------------------


function SqlNull($SqlValue) 
	{
// insert the string "Null" into a null variable, for compatibility with Access SQL.
	if (((string)$SqlValue==""))
		{(string)$SqlValue='NULL';return ($SqlValue);}
	else
		{return ($SqlValue);}
	}
?>

@aag
Ich habe beim im die Daten nach Kategorien in einzeln Datenbanken gespeichert.
z.B. Heizung, Zähler, Wetter
einfach die Daten schon vorsortiert

Danke allseits. Jetzt habe ich entdeckt, dass PgAdmin einen „graphical query editor“ hat, genauso wie MS Access. Meine Begeisterung für PG lässt sich garnicht mehr in Grenzen halten!!! :slight_smile:

Habe ein kleines Problem. Ich finde es relativ mühsam, jeden String mit utf8_encode zu bearbeiten, damit PG nicht über Umlaute etc. stolpert. Kann mir jemand sagen,

[ul]
[li]ob (und wie) ich PHP.INI einstellen kann, damit alles output prinzipell als Unicode UTF8 herausgegeben wird?
[/li][li]ob ich mit Risiken und Nebewirkungen rechnen muss, wenn ich obiges tue?
[/li][/ul]
danke
AAG

Hier wurden mir ein Paar Lösungen unterbreitet, um zwischen Aktualisierung und Aenderung einer geloggten Variable mit reinem SQL (kein PHP) zu unterscheiden.

Es könnte nützlich sein, zunächst alle Aktualisierungen zu loggen, aber nach 1 Monat (oder Quartal, je nachdem) nur noch die Aenderungen zu archivieren und die Aktualisierungen zu löschen.

Ich finde es relativ mühsam, jeden String mit utf8_encode zu bearbeiten

Vielleicht verstehe ich es auch nicht, das steht bei mir alles in einem Script.

um zwischen Aktualisierung und Aenderung einer geloggten Variable mit reinem SQL (kein PHP) zu unterscheiden.

Warum loggst Du nicht gleich entsprechend.

Für explizite Fragen zu PG würde ich dir das PG-Forum empfehlen. Dort sind einige Profis unterwegs. SQL ist nicht gleich SQL.

Hast völlig recht. Meine Idee wäre, alles zunächst zu loggen (ergibt schöne stufenlose Graphen). Für historische Daten, sagen wir älter als 3 Monate, brauche ich aber weniger Granularität; und dann kann ich Datenreduktion betreiben.

Also dachte ich, jede nacht eine query zu laufen, die mir die älteren Zeilen mit (HASCHANGED = false) löscht. Durch das Hinauswerfen der Aktualisierungen kann ich schätzungsweise 75% der Records wieder löschen. Deswegen scheint mir sinnvoll, zwischen beiden Vorgängen zu differenzieren.