arangodb - 当图遍历的级别加深时,性能会急剧下降

标签 arangodb

我一直在使用arangodb开发一个配置管理系统,它收集一些常见软件的配置数据并传输到一个程序,该程序将根据一些预定义的规则生成这些软件之间的关系,然后将这些关系保存到arangodb中。建立关系后,我提供API来查询数据。一项重要的查询是生成这些软件的拓扑。我使用图遍历来生成具有以下 AQL 的拓扑:

for n in nginx for v,e,p in 0..4 outbound n forward, dispatch, route,INBOUND deployto, referto,monitoron filter @domain in p.edges[0].server_name return {id: v._id, type: v.ci_type}

它可以生成以下拓扑: software relation topology

看起来不错。但是,完成查询大约需要 10 秒,这是 Not Acceptable ,因为数据量不是很大。我检查了所有集合和最大的集合,“前向”边缘集合只有大约 28000 个文档。所以我做了一些测试: 我将深度从 0..4 更改为 0..2,只需要 0.3 秒即可完成查询 我将深度从 0..4 更改为 0..3,大约需要 3 秒 对于 0..4,大约需要 10 秒 由于“前向”边缘上有一个 server_name 属性,因此我添加了一个哈希索引(server_name[*]),但似乎 arangodb 不使用解释执行计划中的索引 有什么可以优化查询的提示吗?为什么在这种情况下不能使用索引?

希望有人能帮我解决这个问题。提前致谢,

最佳答案

首先,我尝试了您的查询,由于某种原因我可以看到:

filter @domain in p.edges[0].server_name

未正确优化。这似乎是一个内部问题,优化规则不够好,我将详细研究这个问题并尝试确保它按预期工作。 因此,在这种情况下,它还无法使用不同的索引,并且不会进行短路以正确中止第 1 级搜索。 对于给您带来的不便,我深表歉意,因为您的操作方式应该是正确的。

现在要快速解决问题,您可以将查询的第一部分拆分为单独的步骤:

这是我修改后的查询的快速版本(不包括 nginx,请参阅较慢的版本)

FOR n IN nginx
  FOR forwarded, e IN 1 OUTBOUND forward
    FILTER @domain IN e.server_name
    /* At this point we only have the relevant first depth vertices*/
    FOR v IN 0..3 OUTBOUND forward, dispatch, route, INBOUND deployto, referto, monitoron
      RETURN {id: v._id, type: v.ci_type}

这是我修改后的查询的一个稍慢的版本(保存您的输出格式,我认为它会比您正在使用的查询更快)

FOR tmp IN(
  FOR n IN nginx
    FOR forwarded, e IN 1 OUTBOUND forward
      FILTER @domain IN e.server_name
      /* At this point we only have the relevant first depth vertices*/
      RETURN APPEND([{id: n._id, type: n.ci_type}],(
       FOR v IN 0..3 OUTBOUND forward, dispatch, route, INBOUND deployto, referto, monitoron
       RETURN {id: v._id, type: v.ci_type}
      )
  )[**]
RETURN tmp

我可以给出一些一般性建议:

  1. (这将在我们修复优化器后起作用)索引的使用:ArangoDB 使用索引选择性的统计/假设(查找数据的效果如何)来决定哪个索引更好。在您的情况下,它可能会假设边缘索引比您的哈希索引更好。您可以尝试在 ["_from", "server_name[*]"] 上创建一个组合的 hash_index,它比 EdgeIndex 更有可能具有更好的估计值,并且可以使用。
  2. 在您给出的示例中,我可以看到有一个从 apppkg 节点开始的“大”右侧部分。在查询中,可以通过两种方式到达该右侧部分: a) nginx -> tomcat <- apppkg b) nginx -> varnish -> lvs -> tomcat <- apppkg 这意味着查询可以多次遍历从 apppkg 开始的子树(对于通往那里的每个路径一次)。当查询深度为 4 并且只有这种拓扑时,这种情况不会发生,但如果路径较短,这也可能是一个问题。如果我没有弄错的话,那么您只对图中的不同顶点感兴趣,并且路径并不重要,对吧?如果是这样,您可以向查询添加选项,以确保不会对任何顶点(和依赖子树)进行两次分析。修改后的查询将如下所示:

    对于 nginx 中的 n 对于 0..4 中的 v、e、p 出站 n 转发、调度、路由、入站部署、引用、监控 选项 {bfs: true, uniqueVertices: "global"} 在 p.edges[0].server_name 中过滤@domain 返回{id:v._id,类型:v.ci_type}

我所做的更改是为遍历添加了选项: bfs: true => 意味着我们进行广度优先搜索而不是深度优先搜索,我们只需要这个来使结果具有确定性并确保深度为 4 的路径的所有顶点都将被正确到达 uniqueVertices: "global"=> 意味着每当在一次遍历中找到一个顶点(因此在您的情况下,对于每个 nginx 分别),它就会被标记并且不会再次查看。

如果您还需要所有不同边缘的列表,您应该使用 uniqueEdges: "global" 而不是 uniqueVertices: "global" 这将使唯一性检查边缘水平。

关于arangodb - 当图遍历的级别加深时,性能会急剧下降,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41735589/

相关文章:

date - 时间戳之间的 Arangodb 天数

java - 我应该如何使用 Spring Boot 连接到 ArangoDB

logging - ArangoDB FOXX 日志记录 : how to

arangodb - 如何在多进程中使用arangodb集合

Arangodb AQL 类似于 SQL 的 NOT IN

kubernetes - Arangodb 在一段时间后停止异步复制

python - 如何在 Django 数据库中使用 Arangodb?

arangodb - 无法在 arangodb 中的三元运算符中使用 for 循环

graph - ArangoDB,如何显示图表?

graph-algorithm - 如何获取图上的孤立顶点