缓慢的 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 运行 更快?

感谢任何意见,
埃拉德

  1. 支持data types follow the JSON specs。您可以通过查看文档来确定数据类型,例如使用网络 UI。在文档编辑器中使用 Code 查看模式将文档视为 JSON:

    "Aerosmith" 是一个字符串,1973 是一个数字,流派是 [ ... ] 数组中的字符串,每首歌曲都是一个 { ... } 对象。还有 nulltruefalse 文字。

    对于确定属性数据类型的编程方式,有 Type check functions,例如TYPENAME() 到 return 数据类型名称为字符串。计算属性 someField 属于哪种数据类型的频率的示例查询:

    RETURN MERGE( FOR c1 IN Collection1
      COLLECT type = TYPENAME(c1.someField) WITH COUNT INTO count
      RETURN { [type]: count }
    )
    
  2. _key 确实总是一个字符串。如果您不确定 someField 是什么,可以使用上面的查询。请分享此信息。

  3. 如果您将一个在 运行-time 时仅 已知的值(此处:文档属性)转换为不同的类型,那么是的,不能使用索引。索引查找只有在您按原样查询值时才有可能。但是,您可以对绑定变量和其他常量值进行类型转换,因为它们在查询编译时是已知的。

  4. 不,文档键总是一个字符串。 _key 属性(主索引)上有一个索引,因此没有性能损失,因为它是一个字符串而不是数值。

  5. arangoimport 有一个选项可以将数字字符串转换为数字,"null"null"true" / "false" 到布尔值 (--convert),但没有强制属性成为字符串的选项。有一个 feature request 添加指定所需数据类型的能力。

    如果您希望数字字符串保留为字符串,请使用 --convert false 关闭自动转换。如果值是源文件中的数字(不在引号中),则您可以在导入文件之前对其进行调整。您还可以使用一次性 AQL 查询将属性转换为特定数据类型:

    FOR c1 IN Collection1
      UPDATE doc WITH { someField: TO_STRING(someField) } IN Collection1
    
  6. 我假设在 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 }