我在 ArangoDB 中使用 IN
运算符时遇到一些性能问题。
简单地说,我有一个计算(在运行时)id 的数组,来自分割函数,我只想获取 Collection 中选定的元素,然后收集或过滤其他数据。
您可以在此处找到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 秒。查询花费大量时间来评估 FILTER 的 IN 运算符。事实上,将为找到的每个文档评估 FILTER
条件。这将与我使用的数据进行大约 100,000 x 500,000/2 比较。
在 2.8 中,使用相同的数据进行相同的查询大约需要 2.7 秒,因此问题似乎不会出现在那里。 2.8 中优化器发生了很多变化,其中导致加速的原因是 IN
表达式将直接在索引中求值。 FILTER
将在那里进行优化。
因此,解决方法之一是在 ArangoDB 2.8 可用时使用它(目前处于测试阶段)。
另一个修复方法是改进优化器,以检测查询中 IN
的右侧是否为 const,以便它可以对结果进行排序并执行 IN
> 使用二分搜索(对数而不是线性复杂度)。但目前还无法实现。
2.7 的解决方法是单独计算 IN
列表,并将其作为数组插入到查询中。这样,IN
列表将是一个常量值,优化器将能够对其进行预排序,以便它可以使用二分搜索。但是,这需要在原始查询之外/之前执行 SPLIT
操作。
更新:在 2.8 中,现在有一个额外的优化器规则,可以针对上述情况和其他情况对 IN
列表值进行预排序。这使得 IN 运算符能够使用二分搜索,具有对数复杂度,而不是某些情况下的线性复杂度。此更改将包含在 2.8 beta2 中。
关于indexing - ArangoDB - IN 运算符非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34200335/