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)的结果?
如果您确定在外循环中循环的每个 items
在 dictionary1
中都有一个匹配项,则可以将查询简化为更简单的等值连接,例如这个:
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
中是否会有一个条目,并且您希望为不匹配返回 null
s,子查询解决方案可以简化为(这删除了函数调用 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
中而没有字典集合名称前缀。
以上建议不应提供数量级的运行时改进,但也许它们有所帮助。
有文档集"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)的结果?
如果您确定在外循环中循环的每个 items
在 dictionary1
中都有一个匹配项,则可以将查询简化为更简单的等值连接,例如这个:
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
中是否会有一个条目,并且您希望为不匹配返回 null
s,子查询解决方案可以简化为(这删除了函数调用 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
中而没有字典集合名称前缀。
以上建议不应提供数量级的运行时改进,但也许它们有所帮助。