使用資料負載
資料負載以單一物件的形式儲存在記憶體內部的快取中。因此,在 ThingWorx 8.5 及更新版本中,不支援直接操作資料負載,因為這可能會造成意想不到的行為與效能問題。當您從物件擷取資料負載內容時,會建立一個 proxy 物件,其會回頭與原始物件進行交談。只會對本機副本進行直接變更,不過函數呼叫會更新原始物件。如果您需要物件的完整副本,以便在更新所有資料之前不會對任何變更進行代理,請使用資源的複製選項。在下面的範例中,針對單一列資料負載,我們使用了包裝函式物件,但針對多列資料負載,我們使用了完整複製選項,因為我們不想更新每列變更。
下列程式碼會建立本機 proxy 物件 (方法呼叫將會更新原始物件並儲存至快取):
Things["data1"] 會按名稱搜尋 "data1" 物件。
Things["data1"].info 會呼叫 "data1" 物件中的 "info" 資料負載內容
var myinfo = Things["data1"].info
下列程式碼會建立完整副本,且不會將變更代理回原始物件:
var myinfo = Resources["InfoTableFunctions"].Clone({ t1: Things["data1"].info });
ThingWorx 8.5 及更新版本中內容資料的處理方式與先前發行版本中有所不同。所有資料現在都會儲存在快取圖層中,從而可在高可用性叢集環境中以本機或遠端方式使用。在先前的環境中,儲存的資料可直接修改,但在快取圖層中,資料必須在變更時移入及移出快取。在叢集環境中,會分佈快取;因此,額外的網路延遲和線路序列化會增加所進行的每個請求的時間。
將大量資料以資料負載形式儲存會非常昂貴,而且可能會導致系統在叢集環境中崩潰。資料負載現在會在變更時完全讀取及寫入內容。在叢集環境中,也會對完整物件進行序列化、反序列化及跨線路傳送。您應該將大型資料負載移至資料庫中,而不是將其儲存在單一內容中。可以將其轉換為使用者定義的表格或放置在資料表中。
在叢集環境中,會使用 Apache Ignite。推送大型物件可能會導致 Ignite 變得無回應。Ignite 佇列將進行寫入及備份,當推送大值時,可能需要花費時間來進行處理,並會導致處理備份。如果備份變得很大,Ignite 系統執行緒將會開始阻塞,這可能導致 Ignite 認為節點無回應而將其關閉。可能有越來越多的資料逾期。
為了在叢集環境中良好運作,可能必須變更應用程式,以減少儲存在內容中之資料的大小。通常資料負載多達數千列時會導致此問題。
範例:排序資料負載
此範例過去用來在新增快取層之前正常運作。它曾用來直接更新記憶體中的表格。
var sort = new Object();
sort.name = yourFieldName;
sort.ascending = booleanValue;
me.yourInfoTable.Sort(sort);
但是,現在的執行方式應如下所示:
建立本機資料負載、進行變更,然後將其指派回物件資料負載內容。
這樣會將物件從快取中提取出來,並建立副本。然後,您可以變更副本而不影響原始內容,直到完成設定為止。
如果不是這種情況,每次接觸資料負載都會導致將整個物件寫入回快取,而這就會導致效能降低。
var localInfoTable = me.yourInfoTable;
var sort = new Object();
sort.name = yourFieldName;
sort.ascending = booleanValue;
localInfoTable.Sort(sort);
me.yourInfoTable = localInfoTable;
範例:更新單一列資料負載的欄位值
錯誤的方式:
此指令集中的每一行都會從快取取得整個資料負載、變更一個值,然後再將其放回到快取中。與快取之間的往返會花費時間,因為它每次都會處理整個資料負載。這會對快取執行六次呼叫,在遠端系統中真的會減慢指令集速度。
Things["data1"].info.v1 = 1;
Things["data1"].info.v2 = 2;
Things["data1"].info.v3 = 3;
正確的方式:
此範例會從快取取得資料負載的副本,在本機更新所有資料,然後再將資料負載放回到快取中。它會將快取呼叫減少到只進行兩次呼叫。
var myinfo = Things["data1"].info
myinfo.v1 = 1
myinfo.v2 = 2
myinfo.v3 = 3
Things["data1"].info = myinfo
範例:跨單一列資料負載更新欄位值
在下面的範例中,您可以看到,當將資料負載指派給本機變數時,它是一個副本。對原始物件所做的變更不會在複製的值中表示出來。
// 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;
範例:多列資料負載的行為變更
在下列範例中,您可以看到,資料負載的副本仍是 proxy 物件。在 proxy 物件上呼叫的方法將會對主物件產生影響。下列範例與 proxy 一致,但與 ThingWorx 8.4 行為有所不同。在 ThingWorx 8.4 中,如果我們執行 me.p2 = prop2,會破斷原始物件的參考。而在 ThingWorx 9 中則不會發生此情況,因為會將它們視為相同的物件 proxy。
// 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);
範例:建構多列資料負載
在此範例中,我們要將列新增至資料負載:
錯誤的方式:
雖然此方式看起來是正確的,因為它使用資料庫 AddRow 中的方法,但實際上其會將該變更代理至迴圈中每個版序的原始物件。這會導致將資料負載寫入至不需要之迴圈的每個版序的快取。
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;
正確的方式:
在此範例中,我們複製了物件,以便我們可以在將其指派回原始物件之前對其進行操作,而不會造成任何影響。
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;
以下範例也適用。因為我們並未使用 proxy 物件方法,因此在指派原始物件之前,不會對其進行變更。
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;
這是否有幫助?