我在ArangoDB中使用IN
运算符时会遇到一些性能问题。
简单地说,我有一个计算(在运行时)的数组,来自分裂函数,我想只获取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
运算符中。
我可以做些什么来解决这些表演问题?
非常感谢!
丹尼尔
答案 0 :(得分:4)
我在toInclude
中对100,000个文档的集合中的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中。