[英]Strange performance problem with UPDATE in ArangoDB
我正在創建一個使用 ArangoDB 作為數據存儲的 Node.js 應用程序。 基本上,我擁有的數據結構是兩個表,一個用於管理所謂的instances
,另一個用於entities
。 我做的是以下內容:
instance
的instances
集合中都有一個文檔。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
語句的性能。 有任何想法嗎?
正如評論中所要求的,這里有一些關於系統設置的信息:
您是否嘗試過解釋或分析查詢?
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.