Mit Infotables arbeiten
Infotables werden im Arbeitsspeicher als einzelnes Objekt im Cache gespeichert. Aus diesem Grund wird in ThingWorx 8.5 und höher die direkte Bearbeitung von Infotables nicht unterstützt, da dies zu unerwartetem Verhalten und Leistungsproblemen führen kann. Wenn Sie eine Infotable-Eigenschaft aus einem Ding abrufen, wird ein Proxy-Objekt erstellt, das mit dem ursprünglichen Objekt kommuniziert. Direkte Änderungen werden nur für die lokale Kopie ausgeführt, aber Funktionsaufrufe aktualisieren das ursprüngliche Objekt. Wenn Sie einen vollständigen Klon des Objekts benötigen, sodass keine Änderungen über einen Proxy weitergeleitet werden, bis alle Daten aktualisiert wurden, verwenden Sie die Klonoption der Ressource. In den Beispielen unten für einzeilige Infotables verwenden wir ein Wrapper-Objekt. Für mehrzeilige Infotables verwenden wir jedoch die Option zum vollständigen Klonen, da wir nicht jede Zeilenänderung aktualisieren möchten.
Durch Folgendes wird ein lokales Proxy-Objekt erstellt (Methodenaufrufe aktualisieren das ursprüngliche Objekt und speichern es im Cache):
Things["data1"] sucht nach einem "data1"-Ding anhand des Namens.
Things["data1"].info – Infotable-Eigenschaft "info" für das "data1"-Ding
var myinfo = Things["data1"].info
Im Folgenden wird ein vollständiger Klon erstellt, ohne dass Änderungen über einen Proxy an das ursprüngliche Objekt zurückgegeben werden:
var myinfo = Resources["InfoTableFunctions"].Clone({ t1: Things["data1"].info });
Eigenschaftsdaten in ThingWorx 8.5 und höher werden anders behandelt als in früheren Versionen. Alle Daten werden jetzt in einer Cache-Schicht gespeichert, sodass Sie lokal oder remote in einer Hochverfügbarkeits-Clustering-Umgebung verwendet werden können. In vorherigen Umgebungen wurden die gespeicherten Daten direkt geändert, aber in der Cache-Schicht müssen Daten beim Ändern in den und aus dem Cache verschoben werden. In einer Clustering-Umgebung wird der Cache verteilt. Daher dauert jede Anforderung durch zusätzliche Netzwerklatenz und kabelgebundene Serialisierung länger.
Das Speichern großer Datenmengen in einer Eigenschaft als Infotable ist jetzt sehr kostspielig und kann Systemabstürze in Cluster-Umgebungen verursachen. Die Infotable wird jetzt vollständig gelesen und bei einer Änderung in die Eigenschaft geschrieben. In einer Cluster-Umgebung wird das vollständige Objekt ebenfalls serialisiert, deserialisiert und über das Netzwerk gesendet. Sie sollten große Infotables in die Datenbank verschieben und diese nicht in einer einzigen Eigenschaft speichern. Sie können in benutzerdefinierte Tabellen konvertiert oder in eine Datentabelle eingefügt werden.
In einer Cluster-Umgebung wird Apache Ignite verwendet. Das Verschieben von großen Objekten kann dazu führen, dass Ignite nicht mehr reagiert. Ignite platziert Schreibvorgänge und Sicherungen in Warteschlangen. Wenn große Werte verschoben werden, kann es einige Zeit dauern, diese Werte zu verarbeiten und die Verarbeitung zu sichern. Wenn die Sicherung groß wird, beginnen Ignite-System-Threads zu blockieren. Dies kann dazu führen, dass Ignite einen Knoten herunterfährt, weil es annimmt, dass dieser nicht reagiert. Die Daten können immer mehr veralten.
Damit Anwendungen in einer Cluster-Umgebung gut funktionieren, müssen sie möglicherweise geändert werden, um die Größe der in Eigenschaften gespeicherten Daten zu verringern. Dies wird in der Regel durch Infotables mit Tausenden von Zeilen bewirkt.
Beispiel: Infotables sortieren
Dieses Beispiel funktionierte, bevor die Caching-Schicht hinzugefügt wurde. Die Tabelle wurde direkt im Arbeitsspeicher aktualisiert.
var sort = new Object();
sort.name = yourFieldName;
sort.ascending = booleanValue;
me.yourInfoTable.Sort(sort);
Dies sollte jetzt jedoch folgendermaßen erfolgen:
Erstellen Sie eine lokale Infotable, nehmen Sie Ihre Änderungen vor, und weisen Sie sie wieder der Ding-Infotable-Eigenschaft zu.
Dadurch wird das Objekt aus dem Cache abgerufen und eine Kopie erstellt. Anschließend können Sie die Kopie ohne Auswirkung auf die ursprüngliche Eigenschaft ändern, bis der Satz abgeschlossen ist.
Anderenfalls würde jede Änderung der Infotable dazu führen, dass das gesamte Objekt in den Cache zurückgeschrieben wird und sich die Leistung dadurch verschlechtert.
var localInfoTable = me.yourInfoTable;
var sort = new Object();
sort.name = yourFieldName;
sort.ascending = booleanValue;
localInfoTable.Sort(sort);
me.yourInfoTable = localInfoTable;
Beispiel: Feldwerte für einzeilige Infotables aktualisieren
Falsch:
Jede Zeile in diesem Skript erhält die gesamte Infotable aus dem Cache, ändert einen Wert und platziert sie dann wieder im Cache. Roundtrips zum Cache sind zeitaufwändig, da jedes Mal die gesamte Infotable verarbeitet wird. Der Cache wird sechsmal aufgerufen, was das Skript in einem Remote-System deutlich verlangsamen kann.
Things["data1"].info.v1 = 1;
Things["data1"].info.v2 = 2;
Things["data1"].info.v3 = 3;
Richtig:
In diesem Beispiel wird ein Klon der Infotable aus dem Cache abgerufen, alle Daten werden lokal aktualisiert und dann wird die Infotable wieder im Cache abgelegt. Dies reduziert die Cache-Aufrufe auf nur zwei.
var myinfo = Things["data1"].info
myinfo.v1 = 1
myinfo.v2 = 2
myinfo.v3 = 3
Things["data1"].info = myinfo
Beispiel: Feldwerte für einzeilige Infotables aktualisieren
Im folgenden Beispiel zeigen wir, dass es sich um einen Klon handelt, wenn eine Infotable einer lokalen Variable zugewiesen wird. Änderungen am ursprünglichen Objekt werden nicht im geklonten Wert dargestellt.
// creates a clone of InfoTable
var myinfo = Things["data1"].info;
// sets value of v1 to 5 in local InfoTable
myinfo.v1 = 5;
// change the orignal data1's v1 field value to 4, will not update the local value, it is still 5
Things["data1"].info.v1 = 4;
// assigning local info table to data2 so its v1 will have a value of 5
Things["data2"].info = myinfo;
Beispiel: Verhaltensänderung mit mehrzeiligen Infotables
Unten sehen Sie, dass der Klon der Infotable immer noch ein Proxy-Objekt ist. Die Methoden, die für das Proxy-Objekt aufgerufen werden, wirken sich auf das Hauptobjekt aus. Folgendes ist mit dem Proxy konsistent, unterscheidet sich jedoch von ThingWorx 8.4 Verhalten. In ThingWorx 8.4 würde me.p2 = prop2 die Referenz zum ursprünglichen Objekt aufheben. In ThingWorx 9 ist dies nicht der Fall, da sie als derselbe Objekt-Proxy behandelt werden.
// An InfoTable local object for the "v1" field
var newEntry = new Object();
newEntry.v1 = 1;
// creates a proxy object from local object prop1 -> me.p1
var prop1 = me.p1;
prop1.v1=4;
// creates a proxy object from local object prop2 -> me.p2
var prop2 = me.p2;
prop2.v1=5;
// updates the me.p1 object, this breaks the proxy between prop1 -> me.p1
me.p1=prop2;
// prop2 reference is unchanged, still proxied
me.p2=prop2;
// this will not change me.p1 since the reference was broken when the object assignement to prop2 was done
prop1.AddRow(newEntry);
// this will update me.p2, the object reference is the same
prop2.AddRow(newEntry);
Beispiel: Mehrzeilige Infotable erstellen
In diesem Beispiel möchten wir einer Infotable Zeilen hinzufügen:
Falsch:
Obwohl dies richtig aussieht, weil eine Methode in der Datenbank verwendet wird (AddRow), wird diese Änderung für jede Iteration in der Schleife tatsächlich über einen Proxy an das ursprüngliche Objekt weitergeleitet. Dies bewirkt, dass die Infotable für jede Iteration der Schleife in den Cache geschrieben wird, was nicht erwünscht ist.
var myinfo = Things["data1"].info;
for (i=0; i < 10; i++) {
var row = new Object();
row.v1 = i;
row.v2 = i * 2;
row.v3 = i * 3;
myinfo.AddRow(row);
}
Things["data1"].info = myinfo;
Richtig:
In diesem Beispiel haben wir das Objekt geklont, sodass wir es ohne Auswirkung bearbeiten können, bis es dem ursprünglichen Objekt wieder zugewiesen wird.
var myinfo = Resources["InfoTableFunctions"].Clone({ t1: Things["data1"].info });
for (i=0; i < 10; i++) {
var row = new Object();
row.v1 = i;
row.v2 = i * 2;
row.v3 = i * 3;
myinfo.AddRow(row);
}
Things["data1"].info = myinfo;
Das folgende Beispiel funktioniert auch. Da keine Proxy-Objektmethoden verwendet werden, wird das ursprüngliche Objekt erst dann geändert, wenn es zugewiesen wurde.
var myinfo = Things["data1"].info;
for (i=0; i < 10; i++) {
var row = new Object();
row.v1 = i;
row.v2 = i * 2* 10;
row.v3 = i * 3* 100;
myinfo.rows[i] = row;
}
Things["data1"].info = myinfo;
War dies hilfreich?