【问题标题】:ArangoDB: performance index in array elementArangoDB:数组元素中的性能索引
【发布时间】:2015-11-25 16:12:54
【问题描述】:

我在 ArangoDB 中有一个集合,其中填充了如下元素:

{

  "id": "XXXXXXXX",
  "relation": [
    {
      "AAAAA": "AAAAA",
    },
    {
      "BBBB": "BBBBBB",
      "field": {
        "v1": 0,
        "v2": 0,
        "v3": 0
      }
    },
    {
      "CCCC": "CCCC",
      "field": {
        "v1": 0,
        "v2": 1,
        "v3": 2
      }
    },
  ]
}

我只想返回具有field.v1 > 0(或 v 值的组合)的元素。 我试过写一个像这样的 AQL 查询,但它不使用索引,而且它对于 200000+ 个元素非常慢。

FOR a in X
    FILTER LENGTH(a.relation) > 0
    LET relation =  a.relation
    FOR r in relation
        FILTER r.field > null 
        FILTER r.field.v1 > 0
return a

我已尝试创建这些索引:

  • full text on relation[*]field
  • skip list on relation[*]field
  • hash on relation[*]field 但没有结果。

我能做什么?您能建议我对查询进行任何更改吗?

谢谢。

最好的问候,

丹尼尔

【问题讨论】:

    标签: performance indexing arangodb


    【解决方案1】:

    我建议进行以下更改,但它们不会明显加快查询速度:

    • 过滤器FILTER r.field > nullFILTER r.field.v1 > 0 是多余的。您可以只使用后者FILTER r.field.v1 > 0 并省略其他过滤条件

    • 辅助变量LET relation = a.relation 是在a.relation 用于LENGTH(a.relation) 计算之后定义的。如果辅助变量将在LENGTH() 计算之前定义,则可以在其中使用它,如下所示:LET relation = a.relation FILTER LENGTH(relation) > 0。这将节省一些处理时间

    • 原始查询会检查每个 v1 值,如果文档中的多个 v1 值满足过滤条件,则可能会多次返回每个文档。这意味着原始查询可能返回比集合中实际存在的文档更多的文档。如果不需要,我建议使用子查询(见下文)

    当将上述修改应用于原始查询时,这是我想出的:

    FOR a IN X 
      LET relation = a.relation
      FILTER LENGTH(relation) > 0 
      LET s = (
        FOR r IN relation
          FILTER r.field.v1 > 0 
          LIMIT 1 
          RETURN 1
      )
      FILTER LENGTH(s) > 0 
      RETURN a
    

    正如我所说,这可能不会大大提高性能,但是,您可能会从查询中得到不同的(可能是所需的)结果,即如果文档中的多个 v1 满足过滤条件,则文档会更少。

    关于索引:全文索引和哈希索引在这里没有帮助,因为它们只支持相等比较,但是查询的过滤条件大于。一般而言,唯一可能对这里有益的索引类型是跳过列表索引。但是,2.7 根本不支持索引数组值,因此索引 relation[*].field 将无济于事,并且仍然不会使用您报告的索引。

    ArangoDB 2.8 将是第一个支持索引单个数组值的版本,您可以在relation[*].field.v1 上创建索引。

    2.8 中的查询仍然不会使用该索引,因为数组索引仅用于IN 比较运算符。它们不能与查询中的> 一起使用。此外,当将过滤条件写为FILTER r[*].field.v1 > 0 时,对于上面的示例文档,这将评估为FILTER [null, 0, 0] > 0,这不会产生所需的结果。

    这里可以提供帮助的是一个比较运算符修改器(工作名称),它可以告诉运算符<<=>>===!= 对所有运算符运行比较其左操作数的成员。可能存在ALLANY 修改,因此过滤条件可以简单地写为FILTER a.relation[*].field.v1 ANY > 0。但请注意,这还不是一个现有的功能,而只是我对未来如何解决此问题的快速草稿。

    【讨论】:

    • 非常感谢stj!随着数组索引的改进,我肯定在等待新的 2.8 版本。丹尼尔
    【解决方案2】:

    全文索引目前只能与the FULLTEXT() function一起使用。

    目前无法使用索引来确定子对象的长度。一旦它们成为现实,这将是一个可以使用function defined indices 解决的问题。

    目前,获得可用性能的唯一方法是在将文档写入集合时记住另一个属性的长度:

    {
      "id": "XXXXXXXX",
      "length": 6,
      "relation": [
        {
          "AAAAA": "AAAAA",
        },
        {
          "BBBB": "BBBBBB",
          "field": {
            "v1": 0,
            "v2": 0,
            "v3": 0
          }
        },
        {
          "CCCC": "CCCC",
          "field": {
            "v1": 0,
            "v2": 1,
            "v3": 2
          }
        },
      ]
    }
    

    you look like you want to be using graph features for your data layout?

    【讨论】:

    • 问题在于过滤器'field.v1 > 0',而不是数组的长度。如果没有性能问题,我无法在现场查找。谢谢
    • 您必须能够过滤外部FOR 中可索引的内容,以便内部FOR 获得预选的子集。否则查询将始终以全表扫描告终。您可能已经尝试过使用explain to revalidate whether the Indexes are used
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-23
    • 2011-10-08
    • 2012-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多