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 秒。查询花费大量时间评估那里的 FILTER
s 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 中。
我在 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 秒。查询花费大量时间评估那里的 FILTER
s 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 中。