簡體   English   中英

如何改善arangodb中的更新查詢

[英]How to improve Update query in arangodb

我的收藏館藏有超過1500萬份文檔。 在這1500萬份文檔中,我每小時更新2萬條記錄。 但是更新查詢需要很長時間才能完成(大約30分鍾)。

文獻:

{“ inst”:“ instance1”,“ dt”:“ 2015-12-12T00:00:000Z”,“ count”:10}

我有一個包含20k實例要更新的數組。

我的查詢如下所示:

For h in hourly filter h.dt == DATE_ISO8601(14501160000000) 
   For i in instArr
      filter i.inst == h.inst
      update h with {"inst":i.inst, "dt":i.dt, "count":i.count} in hourly

有沒有優化的方法來做到這一點。 我在inst上有哈希索引,在dt上有skiplist索引。

更新資料

我無法在查詢中手動使用20k inst,因此以下是僅2 inst的執行計划:

 FOR r in hourly FILTER r.dt == DATE_ISO8601(1450116000000) FOR i IN [{"inst":"0e649fa22bcc5200d7c40f3505da153b", "dt":"2015-12-14T18:00:00.000Z"}, {}] FILTER i.inst == r.inst UPDATE r with {"inst":i.inst, "dt": i.dt, "max":i.max, "min":i.min, "sum":i.sum, "avg":i.avg, "samples":i.samples} in hourly OPTIONS { ignoreErrors: true } RETURN NEW.inst Execution plan: Id NodeType Est. Comment 1 SingletonNode 1 * ROOT 5 CalculationNode 1 - LET #6 = [ { "inst" : "0e649fa22bcc5200d7c40f3505da153b", "dt" : "2015-12-14T18:00:00.000Z" }, { } ] /* json expression */ /* const assignment */ 13 IndexRangeNode 103067 - FOR r IN hourly /* skiplist index scan */ 6 EnumerateListNode 206134 - FOR i IN #6 /* list iteration */ 7 CalculationNode 206134 - LET #8 = i.`inst` == r.`inst` /* simple expression */ /* collections used: r : hourly */ 8 FilterNode 206134 - FILTER #8 9 CalculationNode 206134 - LET #10 = { "inst" : i.`inst`, "dt" : i.`dt`, "max" : i.`max`, "min" : i.`min`, "sum" : i.`sum`, "avg" : i.`avg`, "samples" : i.`samples` } /* simple expression */ 10 UpdateNode 206134 - UPDATE r WITH #10 IN hourly 11 CalculationNode 206134 - LET #12 = $NEW.`inst` /* attribute expression */ 12 ReturnNode 206134 - RETURN #12 Indexes used: Id Type Collection Unique Sparse Selectivity Est. Fields Ranges 13 skiplist hourly false false n/a `dt` [ `dt` == "2015-12-14T18:00:00.000Z" ] Optimization rules applied: Id RuleName 1 move-calculations-up 2 move-filters-up 3 move-calculations-up-2 4 move-filters-up-2 5 remove-data-modification-out-variables 6 use-index-range 7 remove-filter-covered-by-index Write query options: Option Value ignoreErrors true waitForSync false nullMeansRemove false mergeObjects true ignoreDocumentNotFound false readCompleteInput true 

我假設選擇部分(而不是更新部分)將成為此查詢的瓶頸。

該查詢似乎有問題,因為對於每個與第一個過濾器匹配的文檔( h.dt == DATE_ISO8601(...) ),將在instArr數組中的20,000個值上進行迭代。 如果instArr值是唯一的,則將僅匹配其中的一個值。 另外,沒有索引將用於內部循環,因為索引選擇已在外部循環中發生。

與其遍歷instArr所有值, instArr將附帶的==比較變成IN比較。 如果instArr是實例名稱的數組,這已經可以工作,但是它似乎是實例對象的數組(至少由instcount屬性組成)。 為了在IN比較中使用實例名稱,最好有一個專用的實例名稱數組,以及一個用於countdt值的轉換表。

以下是使用JavaScript生成這些代碼的示例:

var instArr = [ ], trans = { }; 
for (i = 0; i < 20000; ++i) { 
  var instance = "instance" + i;
  var count = Math.floor(Math.random() * 10);
  var dt = (new Date(Date.now() - Math.floor(Math.random() * 10000))).toISOString();
  instArr.push(instance);        
  trans[instance] = [ count, dt ];  
} 

instArr將如下所示:

[ "instance0", "instance1", "instance2", ... ]

trans

{ 
  "instance0" : [ 4, "2015-12-16T21:24:45.106Z" ], 
  "instance1" : [ 0, "2015-12-16T21:24:39.881Z" ],
  "instance2" : [ 2, "2015-12-16T21:25:47.915Z" ],
  ...
}

然后可以使用綁定變量(如上面的變量那樣命名)將這些數據注入查詢中:

FOR h IN hourly 
  FILTER h.dt == DATE_ISO8601(1450116000000) 
  FILTER h.inst IN @instArr 
  RETURN @trans[h.inst]

請注意,ArangoDB 2.5尚不支持@trans[h.inst]語法。 在該版本中,您將需要編寫:

LET trans = @trans
FOR h IN hourly 
  FILTER h.dt == DATE_ISO8601(1450116000000) 
  FILTER h.inst IN @instArr 
  RETURN trans[h.inst]

另外,2.5的IN列表較長。 IN列表的性能隨IN列表的長度呈二次方下降。 因此,在此版本中,將instArr為最多2,000個值是instArr 這可能需要發出多個具有較小IN列表的查詢,而不是僅發出具有大IN列表的查詢。

更好的選擇是使用ArangoDB 2.6、2.7或2.8,它們沒有此問題,因此不需要解決方法。 除此之外,您還可以在較新的ArangoDB版本中使用稍短的查詢版本。

還要注意,在以上所有示例中,我都使用RETURN ...而不是原始查詢中的UPDATE語句。 這是因為我所有的測試都表明查詢的選擇部分是主要問題,至少與我生成的數據有關。 關於UPDATE原始版本的最后說明:用i.inst更新每個文檔的inst值似乎是i.inst == h.inst ,因為i.inst == h.inst使得該值不會更改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM