簡體   English   中英

ArangoDB 中 UPDATE 的奇怪性能問題

[英]Strange performance problem with UPDATE in ArangoDB

我正在創建一個使用 ArangoDB 作為數據存儲的 Node.js 應用程序。 基本上,我擁有的數據結構是兩個表,一個用於管理所謂的instances ,另一個用於entities 我做的是以下內容:

  • 我擁有的每個instanceinstances集合中都有一個文檔。
  • 每當我向entities集合添加實體時,我還想跟蹤屬於特定實例的實體。
  • 因此,每個instance文檔都有一個用於entities的數組字段,我將實體的 ID 推送到該數組中。

下面的代碼顯示了大綱:

// Connect to ArangoDB.
db = new Database(...);
db.useBasicAuth(user, password);

// Use the database.
await db.createDatabase(database);
db.useDatabase(database);

// Create the instance collection.
instanceCollection = db.collection(`instances-${uuid()}`);
await instanceCollection.create();

// Create the entities collection.
entityCollection = db.collection(`entities-${uuid()}`);
await entityCollection.create();

// Setup an instance.
instance = {
  id: uuid(),
  entities: []
};

// Create the instance in the database.
await db.query(aql`
  INSERT ${instance} INTO ${instanceCollection}
`);

// Add lots of entities.
for (let i = 0; i < scale; i++) {
  // Setup an entity.
  const entity = {
    id: uuid()
  };

  // Update the instance.
  instance.entities.push(entity);

  // Insert the entity in the database.
  await db.query(aql`
    INSERT ${entity} INTO ${entityCollection}
  `);

  // Update the instance in the database.
  await db.query(aql`
    FOR i IN ${instanceCollection}
      FILTER i.id == ${instance.id}
      UPDATE i WITH ${instance} IN ${instanceCollection} OPTIONS { mergeObjects: false }
  `);
}

現在的問題是,我添加的實體越多,這會變得非常慢。 它基本上呈指數增長,盡管我預計會呈線性增長:

Running benchmark 'add and update'
  100 Entities:   348.80ms [+0.00%]
 1000 Entities:  3113.55ms [-10.74%]
10000 Entities: 90180.18ms [+158.54%]

添加索引會產生影響,但不會對整體問題產生任何影響:

Running benchmark 'add and update with index'
  100 Entities:   194.30ms [+0.00%]
 1000 Entities:  2090.15ms [+7.57%]
10000 Entities: 89673.52ms [+361.52%]

問題可以追溯到UPDATE語句。 如果您忽略它而只使用數據庫的INSERT語句,則事情會線性擴展。 因此,更新本身似乎有問題。 但是,我不明白問題出在哪里。

這就是我想理解的:為什么UPDATE語句隨着時間的推移變得顯着變慢? 我用錯了嗎? 這是 ArangoDB 中的已知問題嗎? ……?

感興趣的是討論這種方法:請按照給定的方式進行。 讓我們關注UPDATE語句的性能。 有任何想法嗎?

更新

正如評論中所要求的,這里有一些關於系統設置的信息:

  • ArangoDB 3.4.6、3.6.2.1 和 3.7.0-alpha.2(均在 Docker、macOS 和 Linux 上運行)
  • 單服務器設置
  • ArangoJS 6.14.0(我們在早期版本中也有這個,雖然我不能說出確切的版本)

發現問題

您是否嘗試過解釋或分析查詢?

Arango 的解釋計划描述非常好。 您可以使用內置的 Aardvark Web 管理界面或使用db._explain(query)訪問explain 這是你的樣子:

Execution plan:
 Id   NodeType                  Est.   Comment
  1   SingletonNode                1   * ROOT
  5   CalculationNode              1     - LET #5 = { "_key" : "123", "_id" : "collection/123", "_rev" : "_aQcjewq---", ...instance }   /* json expression */   /* const assignment */
  2   EnumerateCollectionNode      2     - FOR i IN collection   /* full collection scan, projections: `_key`, `id` */   FILTER (i.`id` == "1")   /* early pruning */
  6   UpdateNode                   0       - UPDATE i WITH #5 IN pickups 

Indexes used:
 By   Name      Type      Collection   Unique   Sparse   Selectivity   Fields       Ranges
  6   primary   primary   pickups      true     false       100.00 %   [ `_key` ]   i

問題

計划中的關鍵部分是- FOR i IN collection /* full collection scan完全集合掃描將......很慢。 它應該隨着您收藏的大小線性增長。 因此, for scale迭代的for循環,這絕對意味着集合大小呈指數增長。

解決方案

索引id應該會有所幫助,但我認為這取決於您如何創建索引。

使用_key而不是 index 更改計划以顯示primary

- FOR i IN pickups   /* primary index scan, index only, projections: `_key` */    

這應該是恆定時間,所以for scale迭代的for循環,這應該意味着線性時間。

暫無
暫無

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

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