Arangodb 性能:边缘与 DOCUMENT()
Arango DB performace: edge vs. DOCUMENT()
我是 arangoDB 的图表新手。我只是想知道构建边缘或使用 'DOCUMENT()' 用于不需要查询图形的非常简单的 1:1 连接是否更快?
LET a = DOCUMENT(@from)
FOR v IN OUTBOUND a
CollectionAHasCollectionB
RETURN MERGE(a,{b:v})
对
LET a = DOCUMENT(@from)
RETURN MERGE(a,{b:DOCUMENT(a.bId)}
一般来说,后一种变体
LET a = DOCUMENT(@from)
RETURN MERGE(a,{b:DOCUMENT(a.bId)}
应该比全功能遍历变体具有更低的开销。这是因为 DOCUMENT 变体将对文档进行点查找,而遍历变体是非常通用的目的:它可以 return 从可变数量的集合中得到零到多个结果,需要跟踪看到的路径等.
当我在本地测试用例中尝试两种变体时,非遍历变体也快很多,支持这一说法。
然而,基于遍历的变体更灵活:如果有多个边(没有 1:1 映射)和更长的路径,它也可以使用。
您可以尝试的简单基准测试:
创建集合 products
、categories
和边缘集合 has_category
。然后生成一些样本数据:
FOR i IN 1..10000
INSERT {_key: TO_STRING(i), name: CONCAT("Product ", i)} INTO products
FOR i IN 1..10000
INSERT {_key: TO_STRING(i), name: CONCAT("Category ", i)} INTO categories
FOR p IN products
LET random_categories = (
FOR c IN categories
SORT RAND()
LIMIT 5
RETURN c._id
)
LET category_subset = SLICE(random_categories, 0, RAND()*5+1)
UPDATE p WITH {
categories: category_subset,
categoriesEmbedded: DOCUMENT(category_subset)[*].name
} INTO products
FOR cat IN category_subset
INSERT {_from: p._id, _to: cat} INTO has_category
然后比较不同方法的查询时间。
图遍历(深度1..1):
FOR p IN products
RETURN {
product: p.name,
categories: (FOR v IN OUTBOUND p has_category RETURN v.name)
}
使用 DOCUMENT() 在类别集合中查找:
FOR p IN products
RETURN {
product: p.name,
categories: DOCUMENT(p.categories)[*].name
}
使用直接嵌入的类别名称:
FOR p IN products
RETURN {
product: p.name,
categories: p.categoriesEmbedded
}
图遍历是所有 3 个中最慢的,在另一个集合中查找比遍历快,但到目前为止最快的查询是嵌入类别名称的查询。
但是,如果您只查询一个或几个产品的类别,无论数据模型和查询方法如何,响应时间都应该在亚毫秒范围内,因此不会造成性能问题。
如果您需要查询具有可变深度、长路径、最短路径等的路径,则应选择图形方法。对于您的用例,这不是必需的。嵌入式方法是否合适是你需要决定的事情:
重复信息是否可以接受,并且数据可能存在不一致? (如果要更改类别名称,则需要在所有产品记录中更改它,而不是只更改一个类别文档,该产品可以通过不可变ID引用)
每个类别是否有很多附加信息?如果是这样,所有这些数据都需要嵌入到每个具有该类别的产品文档中——基本上是用内存/存储 space 换取性能
您是否需要经常检索所有(不同)类别的列表?您可以使用单独的类别集合非常便宜地执行此类查询。使用嵌入式方法,效率会低很多,因为您需要遍历所有产品并收集类别信息。
底线:您应该选择最适合您的用例的数据模型和方法。由于 ArangoDB 的多模型特性,如果您的用例发生变化或者您 运行 遇到性能问题,您可以轻松尝试另一种方法。
我是 arangoDB 的图表新手。我只是想知道构建边缘或使用 'DOCUMENT()' 用于不需要查询图形的非常简单的 1:1 连接是否更快?
LET a = DOCUMENT(@from)
FOR v IN OUTBOUND a
CollectionAHasCollectionB
RETURN MERGE(a,{b:v})
对
LET a = DOCUMENT(@from)
RETURN MERGE(a,{b:DOCUMENT(a.bId)}
一般来说,后一种变体
LET a = DOCUMENT(@from)
RETURN MERGE(a,{b:DOCUMENT(a.bId)}
应该比全功能遍历变体具有更低的开销。这是因为 DOCUMENT 变体将对文档进行点查找,而遍历变体是非常通用的目的:它可以 return 从可变数量的集合中得到零到多个结果,需要跟踪看到的路径等.
当我在本地测试用例中尝试两种变体时,非遍历变体也快很多,支持这一说法。
然而,基于遍历的变体更灵活:如果有多个边(没有 1:1 映射)和更长的路径,它也可以使用。
您可以尝试的简单基准测试:
创建集合 products
、categories
和边缘集合 has_category
。然后生成一些样本数据:
FOR i IN 1..10000
INSERT {_key: TO_STRING(i), name: CONCAT("Product ", i)} INTO products
FOR i IN 1..10000
INSERT {_key: TO_STRING(i), name: CONCAT("Category ", i)} INTO categories
FOR p IN products
LET random_categories = (
FOR c IN categories
SORT RAND()
LIMIT 5
RETURN c._id
)
LET category_subset = SLICE(random_categories, 0, RAND()*5+1)
UPDATE p WITH {
categories: category_subset,
categoriesEmbedded: DOCUMENT(category_subset)[*].name
} INTO products
FOR cat IN category_subset
INSERT {_from: p._id, _to: cat} INTO has_category
然后比较不同方法的查询时间。
图遍历(深度1..1):
FOR p IN products
RETURN {
product: p.name,
categories: (FOR v IN OUTBOUND p has_category RETURN v.name)
}
使用 DOCUMENT() 在类别集合中查找:
FOR p IN products
RETURN {
product: p.name,
categories: DOCUMENT(p.categories)[*].name
}
使用直接嵌入的类别名称:
FOR p IN products
RETURN {
product: p.name,
categories: p.categoriesEmbedded
}
图遍历是所有 3 个中最慢的,在另一个集合中查找比遍历快,但到目前为止最快的查询是嵌入类别名称的查询。
但是,如果您只查询一个或几个产品的类别,无论数据模型和查询方法如何,响应时间都应该在亚毫秒范围内,因此不会造成性能问题。
如果您需要查询具有可变深度、长路径、最短路径等的路径,则应选择图形方法。对于您的用例,这不是必需的。嵌入式方法是否合适是你需要决定的事情:
重复信息是否可以接受,并且数据可能存在不一致? (如果要更改类别名称,则需要在所有产品记录中更改它,而不是只更改一个类别文档,该产品可以通过不可变ID引用)
每个类别是否有很多附加信息?如果是这样,所有这些数据都需要嵌入到每个具有该类别的产品文档中——基本上是用内存/存储 space 换取性能
您是否需要经常检索所有(不同)类别的列表?您可以使用单独的类别集合非常便宜地执行此类查询。使用嵌入式方法,效率会低很多,因为您需要遍历所有产品并收集类别信息。
底线:您应该选择最适合您的用例的数据模型和方法。由于 ArangoDB 的多模型特性,如果您的用例发生变化或者您 运行 遇到性能问题,您可以轻松尝试另一种方法。