ArangoDB - IN 运算符非常慢

ArangoDB - IN operator very slow

我在 ArangoDB 中使用 IN 运算符时遇到一些性能问题。

简而言之,我有一个计算的(在运行时)id 数组,来自一个拆分函数,我只想获取集合中的选定元素,然后收集或过滤其他数据。

在这里您可以找到 AQL 查询:

LET toInclude = SPLIT('Collection/1,Collection/2,Collection/3', ',')

FOR result IN Collection
  FILTER result._id IN toInclude  
  COLLECT property = result.property 
  WITH COUNT INTO count
return  {property, count}

数组toInclude中的元素可以达到300000+,查询需要10多分钟才能完成。

split - 函数在 3 秒内完成,property 字段已编入索引,因此问题出在 IN 运算符中。

我能做些什么来解决这个性能问题?

非常感谢!

丹妮尔

我在 100,000 个文档的集合上尝试了 toInclude 中包含 500,000 个字符串条目的查询。

2.7确实花了很长时间才完成。执行时间约为 4xx 秒。查询花费大量时间评估那里的 FILTERs IN 运算符。事实上, FILTER 条件将针对找到的每个文档进行评估。这将与我使用的数据进行大约 100,000 x 500,000 / 2 次比较。

在 2.8 中,相同的查询使用相同的数据大约需要 2.7 秒,因此问题似乎不会出现在那里。 2.8 中有很多优化器更改,负责加速的是 IN 表达式将直接在索引中求值。 FILTER 将在那里进行优化。

因此,一种解决方法是在可用时使用 ArangoDB 2.8(目前处于测试阶段)。

另一个修复方法是改进优化器以检测 IN 的右侧在查询中是常量,因此它可以对结果进行排序并可以使用二进制执行 IN搜索(对数而不是线性复杂度)。但这还不可用。

2.7 的解决方法是单独计算 IN 列表并将其作为数组插入到查询中。这样 IN 列表将是一个常量值,优化器将能够对其进行预排序,以便它可以使用二进制搜索。但是,这需要在 of/before 原始查询之外执行 SPLIT 操作。

更新:在 2.8 中,现在有一个额外的优化器规则来为上述情况和其他情况预排序 IN 列表值。这使 IN 运算符能够使用二进制搜索,具有对数复杂性而不是某些情况下的线性复杂性。此更改将包含在 2.8 beta2 中。