Arangodb AQL过滤器不是IN集合,非常慢

时间:2015-02-10 17:13:53

标签: arangodb aql

我想找到没有配置文件的用户组。

ArangoDB 2.4.3

LENGTH(users) -> 130k
LENGTH(profiles) -> 110k

users.userId -> unique hash index
profiles.userId -> unique hash index

我制作的AQL片段比夏季中期穿越大峡谷的蜗牛要慢。

LET usersWithProfiles = ( /* This part is ok */
FOR i IN users
    FOR j IN profiles
        FILTER i.userId == j.userId
RETURN i
)

LET usersWithoutProfiles = ( /* This is not */
FOR i IN usersWithProfiles
    FILTER i NOT IN users
RETURN i
)

RETURN LENGTH(usersWithoutProfiles)

我很确定有一种完全正确的做法,但是我很想念它。有什么想法吗?

编辑1 (在 dothebart 的回复之后):

这是新查询,但仍然很慢

LET userIds_usersWithProfile = (
FOR i IN users
    FOR j IN profile
        FILTER i.userId == j.userId
RETURN i.userId
)

LET usersWithoutProfiles = (
FOR i IN users 
    FILTER i.userId NOT IN userIds_usersWithProfile
RETURN i
)

RETURN LENGTH(usersWithoutProfiles)

2 个答案:

答案 0 :(得分:6)

另请注意,原始查询的这一部分非常昂贵:

LET usersWithoutProfiles = (
  FOR i IN usersWithProfiles
    FILTER i NOT IN users
    RETURN i
)

原因是FILTER使用users,此时这是一个表达式,它将集合中的所有文档构建为数组。 我建议使用此查询,而不是使用此查询,该查询将返回没有关联的配置文件记录的用户的_key属性:

FOR user IN users 
  LET profile = (
    FOR profile IN profiles 
      FILTER profile.userId == user.userId 
      RETURN 1
  ) 
  FILTER LENGTH(profile) == 0 
  RETURN user._key

答案 1 :(得分:4)

性能不佳的原因是它无法为您的操作使用索引,因为它需要对集合中的每个文档进行全面比较。

您可以使用explain https://www.arangodb.com/2015/02/02/arangodb-2-4-2实用程序让arangodb告诉您查询的费用在哪里。

您的查询可能无法满足您的期望。 usersWithoutProfiles将为空,因为任何具有配置文件的用户都将在users集合中找到。如果您想拥有users集合的其他部分,它可能看起来像这样:

LET usersWithProfiles = ( /* This part is ok */
FOR i IN users
    FOR j IN profiles
        FILTER i.userId == j.userId
RETURN i
)

/* now we pick the IDs, we could have done that in your first query... */
LET userWithProfilesIds = FOR i IN userWithProfiles RETURN i.userId;

/* now filter the user list by that */
LET usersWithoutProfiles = FOR i IN users 
     FILTER i.userId NOT IN userWithProfileIds
     RETURN i;

RETURN LENGTH(usersWithoutProfiles)

应该给你一个合适的结果。

相关问题