【问题标题】:Performance drop dramatically when levels get deeper in graph travelsal当层级在图遍历中变得更深时,性能会急剧下降
【发布时间】:2017-01-19 06:57:01
【问题描述】:

我一直在使用 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 秒,这是不可接受的,因为卷不是很大。我检查了所有集合和最大的集合,“前向”边缘集合只有大约 28000 个文档。所以我做了一些测试: 我将深度从 0..4 更改为 0..2,完成查询只需要 0.3 秒 我将深度从 0..4 更改为 0..3,大约需要 3 秒 对于 0..4,大约需要 10 秒 由于“转发”边缘有一个 server_name 属性,所以我添加了一个哈希索引(server_name [*]),但似乎 arangodb 没有使用解释执行计划中的索引 我可以优化查询的任何提示?以及为什么在这种情况下不能使用索引?

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

【问题讨论】:

  • 我也见过这样的查询速度变慢,但速度变慢的原因有时可能只是返回的数据量。您是否尝试在返回 0..2 与 0..4 的数据时测量响应的大小?想知道响应的大小是否有任何惊喜。
  • 其实返回数据是在一个小集合里。它是一个包含大约 400 个元素的向量,具有 0..4 的两字段哈希图。

标签: arangodb


【解决方案1】:

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

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 varnish -> lvs -> tomcat

    在 Nginx 中为 n for v,e,p in 0..4 outbound n forward, dispatch, route, INBOUND deployto, refer to, monitoron 选项 {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",这将在边缘级别进行唯一性检查。

【讨论】:

  • ,感谢您提供如此丰富的回复和有用的建议。 #1 建议正是我接下来要测试的内容,我期待您对查询优化器的更新。
  • 嗨,@mchacki,我应用了#2,时间下降到 2 秒。这很棒,但我希望它可以在 1 秒内完成。所以我能问一下#1的进展吗?我现在可以使用边缘的某些属性的索引吗?
猜你喜欢
  • 1970-01-01
  • 2023-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-06
  • 1970-01-01
  • 2021-07-19
  • 2015-12-24
相关资源
最近更新 更多