首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当图中的级别变得更深时,性能会急剧下降

当图中的级别变得更深时,性能会急剧下降
EN

Stack Overflow用户
提问于 2017-01-19 14:57:02
回答 1查看 136关注 0票数 2

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

代码语言:javascript
复制
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秒才能完成查询,这是不可接受的,因为数据量不是很大。我检查了所有的集合和最大的集合,"forward“边缘集合只有大约28000个文档。所以我做了一些测试:我把深度从0..4改为0..2,只用了0.3秒就完成了查询我把深度从0..4改成了0..3,0..4大约需要3秒,因为在“前进”边缘有一个server_name属性,所以需要大约10秒,所以我添加了一个散列索引(server_name*),但是似乎arangodb没有使用explain execute plan中的索引,有什么提示我可以优化查询吗?为什么在这种情况下不能使用索引?

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

EN

回答 1

Stack Overflow用户

发布于 2017-01-20 18:07:23

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

代码语言:javascript
复制
filter @domain in p.edges[0].server_name

未正确优化。这似乎是一个内部问题,优化规则不够好,我将对此进行详细研究,并尝试确保它如预期的那样工作。由于这个原因,它还不能在这种情况下使用不同的索引,并且不会在级别1上正确中止搜索的短路。我很抱歉给您带来不便,因为您做的方式应该是正确的。

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

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

代码语言:javascript
复制
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}

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

代码语言:javascript
复制
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且仅此拓扑的情况下,不会发生这种情况,但如果存在较短的路径,这也可能是一个问题。如果我没记错的话,那么你只对图中不同的顶点感兴趣,路径并不重要,对吗?如果是这样的话,您可以向查询添加选项,以确保没有顶点(和依赖子树)被分析两次。修改后的查询将如下所示:

for n in nginx for v,e,p in 0..4出站n转发,调度,路由,入站部署,参考,监控选项{bfs: true,uniqueVertices:"global"} filter @ p.edges.server_name in p.edges.server_name返回{id: v._id,类型: v.ci_type}

我所做的改变是我在遍历中添加了选项: bfs: true =>意味着我们进行广度优先搜索,而不是深度优先搜索,我们只需要这样做就可以使结果具有确定性,并确保路径为4的所有顶点都将被正确到达uniqueVertices:“=>”全局意味着只要在一次遍历中发现一个顶点(所以在您的例子中,每个nginx都是单独的),它就会被标记,不会再被查看。

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41735589

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档