Graph Arango DB性能:边缘与文件()

Graph Arango DB性能:边缘与文件(),graph,arangodb,query-performance,aql,Graph,Arangodb,Query Performance,Aql,我不熟悉arangoDB的图形。我只是想知道,对于不需要查询图形的非常简单的1:1连接,构建边或使用“DOCUMENT()”是否更快 LET a = DOCUMENT(@from) FOR v IN OUTBOUND a CollectionAHasCollectionB RETURN MERGE(a,{b:v}) vs 一般来说,后一种变体 LET a = DOCUMENT(@from) RETURN MERGE(a,{b:DOCUMENT(a.bId)} 应具有比全功能遍历变体更低的开销

我不熟悉arangoDB的图形。我只是想知道,对于不需要查询图形的非常简单的1:1连接,构建边或使用“DOCUMENT()”是否更快

LET a = DOCUMENT(@from)
FOR v IN OUTBOUND a
CollectionAHasCollectionB
RETURN MERGE(a,{b:v})
vs


一般来说,后一种变体

LET a = DOCUMENT(@from)
RETURN MERGE(a,{b:DOCUMENT(a.bId)}
应具有比全功能遍历变体更低的开销。这是因为文档变量将对文档进行点查找,而遍历变量是非常通用的:它可以从可变数量的集合返回零到多个结果,需要跟踪所看到的路径等

当我在本地测试用例中尝试这两种变体时,非遍历变体也要快得多,支持这一说法


但是,基于遍历的变体更灵活:如果有多条边(不是1:1映射)和更长的路径,也可以使用它。

一个简单的基准,您可以尝试:

创建集合
产品
类别
,边缘集合
具有_类别
。然后生成一些示例数据:

FOR i IN 1..10000
    INSERT {_key: TO_STRING(i), name: CONCAT("Product ", i)} INTO products
然后比较不同方法的查询时间

图形遍历(深度1..1):

使用文档()在类别集合中查找:

使用直接嵌入的类别名称:

FOR p IN products
    RETURN {
        product: p.name,
        categories: p.categoriesEmbedded
    }
图形遍历是所有3个查询中最慢的,在另一个集合中的查找速度比遍历速度快,但到目前为止最快的查询是具有嵌入类别名称的查询

但是,如果只查询一个或几个产品的类别,则响应时间应在亚毫秒范围内,而不管数据模型和查询方法如何,因此不会造成性能问题

如果您需要查询具有可变深度、长路径、最短路径等的路径,则应选择图形方法。对于您的用例,这是不必要的。您需要确定嵌入式方法是否合适:

  • 是否可以接受重复信息,并且数据中可能存在不一致?(如果要更改类别名称,则需要在所有产品记录中更改它,而不是仅在一个类别文档中更改它,这些产品可以通过不可变ID引用)

  • 每个类别是否有很多附加信息?如果是这样的话,所有这些数据都需要嵌入到每个具有该类别的产品文档中——基本上是以内存/存储空间换取性能

  • 您是否需要经常检索所有(不同)类别的列表?使用单独的categories集合可以非常便宜地执行这种类型的查询。使用嵌入式方法,效率会低很多,因为您需要检查所有产品并收集类别信息


底线:您应该选择最适合您的用例的数据模型和方法。由于ArangoDB的多模型特性,如果您的用例发生变化或遇到性能问题,您可以很容易地尝试另一种方法。

我发现在深度嵌套循环中使用
DOCUMENT()
,其中生成的文档非常大,这将极大地降低性能,并可能导致数据库崩溃。
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
FOR p IN products
    RETURN {
        product: p.name,
        categories: (FOR v IN OUTBOUND p has_category RETURN v.name)
    }
FOR p IN products
    RETURN {
        product: p.name,
        categories: DOCUMENT(p.categories)[*].name
    }
FOR p IN products
    RETURN {
        product: p.name,
        categories: p.categoriesEmbedded
    }