ArangoDB 通过 _id 获取文档,每个查询缓存

ArangoDB get document by _id with cache per query

有文档集"items",以及"dictionary1"、"dictionary2"

collection "items" have 50000 records, like
{
label:"..."
dict1: "dictionary1/33333"
dict2: "dictionary2/44444"
....
}

当我用

加入词典时
FOR item IN items
LET dictname = FIRST(FOR d IN dictionary1 FILTER d._id == item.dict1 RETURN d.name)
RETURN { _id: item._id, name: item.name, dict: dictname }

查询执行时间 ~ 150 毫秒对于这个简单的任务来说太多了。 对于实验,我强制 dict 一个 _id

FOR item IN items
LET dictname = FIRST(FOR d IN dictionary1 FILTER d._id == "dictionary1/10000" RETURN d.name)
RETURN { _id: item._id, name: item.name, dict: dictname }

查询执行时间 ~ 130ms

我也试过 DOCUMENT 函数

FOR item IN items
LET dictname = DOCUMENT("dictionary1", "dictionary1/10000")
RETURN { _id: item._id, name: item.name, dict: dictname.name }

查询执行时间 ~ 1500ms :((

并从集合中简单读取:

FOR item IN items
RETURN { _id: item._id, name: item.name }

查询执行时间~30ms

因此,当我通过 _id 获得相同文档作为连接 50000 次时,结果未被缓存。 一个集合中具有重复内容的变体对我没有用。 现在我将逻辑移至客户端,select 内存中的所有词典并在查询后加入,并且有 ~60ms,但我不喜欢这种方法,它错了。

有什么方法可以在短时间内获得连接词典(80% 相同 _id)的结果?

如果您确定在外循环中循环的每个 itemsdictionary1 中都有一个匹配项,则可以将查询简化为更简单的等值连接,例如这个:

FOR item IN items
  FOR d IN dictionary1 
    FILTER d._id == item.dict1
    RETURN { _id: item._id, name: item.name, dict: d.name }

这消除了对相关子查询和函数调用的需要。但是,如果每个 item 都有匹配的 dictionary 条目,则其结果将仅等同于原始子查询解决方案。如果 item 没有 dictionary 条目,等值连接查询将简单地抑制它。

如果不清楚 dictionary1 中是否会有一个条目,并且您希望为不匹配返回 nulls,子查询解决方案可以简化为(这删除了函数调用 FIRST):

FOR item IN items
  LET sub = (FOR d IN dictionary1 
    FILTER d._id == item.dict1
    RETURN d.name
  )
  RETURN { _id: item._id, name: item.name, dict: sub[0] }

除此之外,加入 _key 属性而不是加入 _id 可能会提供较小的加速,因为 _key 比 [=22= 更短且生成起来更简单].但这将需要将连接值存储在 items 中而没有字典集合名称前缀。

以上建议不应提供数量级的运行时改进,但也许它们有所帮助。