缓慢的 AQL 和数据类型转换,如何提高我的 AQL 性能?
Slow AQL and data type conversion, how can I improve my AQL performance?
你好 ArangoDB 社区,
我已经使用 arangoimport(通过 CSV)将两个集合从 sqlite 导入到 ArangoDB。
接下来,我尝试 运行 一个简单的 AQL 来交叉引用这些集合(最终目标是通过边缘连接它们)。
Collection1 有 1,682,642 个文档
Collection2 有 3,290 个文档
以下 AQL 需要 30 秒才能完成:
FOR c1 IN Collection1
FOR c2 IN Collection2
FILTER c2._key == TO_STRING(c1.someField) return {"C2": c2._id, "C1": c1._id}
如果我这样切换转换,需要很长时间(我在 5 分钟后放弃):
FOR c1 IN Collection1
FOR c2 IN Collection2
FILTER TO_NUMBER(c2._key) == c1.someField return {"C2": c2._id, "C1": c1._id}
在 "someField" 上添加索引没有帮助。
Sqlite 中的相同 JOIN 查询(从中导入数据)只需不到 1 秒即可完成
一些想法和问题:
1) 如何知道文档中字段的数据类型?
2) _key 是一个字符串。我认为 "someField" 是一个数字(因为没有 TO_STRING,没有返回结果)。
3) 在 "someField" 上添加 TO_STRING 是否有效地使字段上的索引不可用?
4)有没有办法让_key成为一个数字(最好是一个整数)。我觉得数字比较更快,不是吗?
5)或者,我可以告诉 arangoimport 强制 "someField" 成为一个字符串吗?
6) 我还能做些什么来使 AQL 运行 更快?
感谢任何意见,
埃拉德
支持data types follow the JSON specs。您可以通过查看文档来确定数据类型,例如使用网络 UI。在文档编辑器中使用 Code 查看模式将文档视为 JSON:
"Aerosmith"
是一个字符串,1973
是一个数字,流派是 [ ... ]
数组中的字符串,每首歌曲都是一个 { ... }
对象。还有 null
、true
和 false
文字。
对于确定属性数据类型的编程方式,有 Type check functions,例如TYPENAME()
到 return 数据类型名称为字符串。计算属性 someField
属于哪种数据类型的频率的示例查询:
RETURN MERGE( FOR c1 IN Collection1
COLLECT type = TYPENAME(c1.someField) WITH COUNT INTO count
RETURN { [type]: count }
)
_key
确实总是一个字符串。如果您不确定 someField
是什么,可以使用上面的查询。请分享此信息。
如果您将一个在 运行-time 时仅 已知的值(此处:文档属性)转换为不同的类型,那么是的,不能使用索引。索引查找只有在您按原样查询值时才有可能。但是,您可以对绑定变量和其他常量值进行类型转换,因为它们在查询编译时是已知的。
不,文档键总是一个字符串。 _key
属性(主索引)上有一个索引,因此没有性能损失,因为它是一个字符串而不是数值。
arangoimport 有一个选项可以将数字字符串转换为数字,"null"
到 null
和 "true"
/ "false"
到布尔值 (--convert
),但没有强制属性成为字符串的选项。有一个 feature request 添加指定所需数据类型的能力。
如果您希望数字字符串保留为字符串,请使用 --convert false
关闭自动转换。如果值是源文件中的数字(不在引号中),则您可以在导入文件之前对其进行调整。您还可以使用一次性 AQL 查询将属性转换为特定数据类型:
FOR c1 IN Collection1
UPDATE doc WITH { someField: TO_STRING(someField) } IN Collection1
我假设在 SQLite 中主键是一个整数值,因此也引用它(外键)。因为在 ArangoDB 中主键必须是字符串,所以引用也需要是字符串类型。更改文档以将外键也存储为字符串。在 someField
(您用于联接的字段)上向 Collection1 添加哈希索引。那么这个查询应该很快并且 return 预期结果:
FOR c1 IN Collection1
FOR c2 IN Collection2
FILTER c2._key == c1.someField
RETURN { C2: c2._id, C1: c1._id }
你好 ArangoDB 社区,
我已经使用 arangoimport(通过 CSV)将两个集合从 sqlite 导入到 ArangoDB。
接下来,我尝试 运行 一个简单的 AQL 来交叉引用这些集合(最终目标是通过边缘连接它们)。
Collection1 有 1,682,642 个文档
Collection2 有 3,290 个文档
以下 AQL 需要 30 秒才能完成:
FOR c1 IN Collection1
FOR c2 IN Collection2
FILTER c2._key == TO_STRING(c1.someField) return {"C2": c2._id, "C1": c1._id}
如果我这样切换转换,需要很长时间(我在 5 分钟后放弃):
FOR c1 IN Collection1
FOR c2 IN Collection2
FILTER TO_NUMBER(c2._key) == c1.someField return {"C2": c2._id, "C1": c1._id}
在 "someField" 上添加索引没有帮助。
Sqlite 中的相同 JOIN 查询(从中导入数据)只需不到 1 秒即可完成
一些想法和问题:
1) 如何知道文档中字段的数据类型?
2) _key 是一个字符串。我认为 "someField" 是一个数字(因为没有 TO_STRING,没有返回结果)。
3) 在 "someField" 上添加 TO_STRING 是否有效地使字段上的索引不可用?
4)有没有办法让_key成为一个数字(最好是一个整数)。我觉得数字比较更快,不是吗?
5)或者,我可以告诉 arangoimport 强制 "someField" 成为一个字符串吗?
6) 我还能做些什么来使 AQL 运行 更快?
感谢任何意见,
埃拉德
支持data types follow the JSON specs。您可以通过查看文档来确定数据类型,例如使用网络 UI。在文档编辑器中使用 Code 查看模式将文档视为 JSON:
"Aerosmith"
是一个字符串,1973
是一个数字,流派是[ ... ]
数组中的字符串,每首歌曲都是一个{ ... }
对象。还有null
、true
和false
文字。对于确定属性数据类型的编程方式,有 Type check functions,例如
TYPENAME()
到 return 数据类型名称为字符串。计算属性someField
属于哪种数据类型的频率的示例查询:RETURN MERGE( FOR c1 IN Collection1 COLLECT type = TYPENAME(c1.someField) WITH COUNT INTO count RETURN { [type]: count } )
_key
确实总是一个字符串。如果您不确定someField
是什么,可以使用上面的查询。请分享此信息。如果您将一个在 运行-time 时仅 已知的值(此处:文档属性)转换为不同的类型,那么是的,不能使用索引。索引查找只有在您按原样查询值时才有可能。但是,您可以对绑定变量和其他常量值进行类型转换,因为它们在查询编译时是已知的。
不,文档键总是一个字符串。
_key
属性(主索引)上有一个索引,因此没有性能损失,因为它是一个字符串而不是数值。arangoimport 有一个选项可以将数字字符串转换为数字,
"null"
到null
和"true"
/"false"
到布尔值 (--convert
),但没有强制属性成为字符串的选项。有一个 feature request 添加指定所需数据类型的能力。如果您希望数字字符串保留为字符串,请使用
--convert false
关闭自动转换。如果值是源文件中的数字(不在引号中),则您可以在导入文件之前对其进行调整。您还可以使用一次性 AQL 查询将属性转换为特定数据类型:FOR c1 IN Collection1 UPDATE doc WITH { someField: TO_STRING(someField) } IN Collection1
我假设在 SQLite 中主键是一个整数值,因此也引用它(外键)。因为在 ArangoDB 中主键必须是字符串,所以引用也需要是字符串类型。更改文档以将外键也存储为字符串。在
someField
(您用于联接的字段)上向 Collection1 添加哈希索引。那么这个查询应该很快并且 return 预期结果:FOR c1 IN Collection1 FOR c2 IN Collection2 FILTER c2._key == c1.someField RETURN { C2: c2._id, C1: c1._id }