简体   繁体   English

ArangoDB - 优化多个查询的交集

[英]ArangoDB - Optimize Intersection of Multiple Queries

I have 4 queries to get the INTERSECTED result from them and do a nested FOR on the next line.我有 4 个查询来从中获取 INTERSECTED 结果并在下一行执行嵌套 FOR。 Is there a way to optimize this query?有没有办法优化这个查询?

Query string:
 LET c0 = (FOR attr IN products_attributes
     FILTER attr.key == "nt1" AND attr.value >= 0 AND attr.value <= 5
 RETURN attr.productId)
 LET c1 = (FOR attr IN products_attributes
     FILTER attr.key == "st1" AND attr.value == "test str"
 RETURN attr.productId)
 LET c2 = (FOR attr IN products_attributes
     FILTER attr.key == "mlt1" AND attr.value == "mo1"
 RETURN attr.productId)
 LET c3 = (FOR attr IN products_attributes
     FILTER attr.key == "mlt1" AND attr.value == "mo2"
 RETURN attr.productId)
 LET collections = INTERSECTION(c0, c1, c2, c3)
 FOR pid IN collections
     FOR p IN products
         FILTER p._key == pid AND "test" IN p.st AND "product" IN p.st
         SORT p.date DESC
         LIMIT 0, 10
         RETURN p

Execution plan:
 Id   NodeType            Est.   Comment
  1   SingletonNode          1   * ROOT
  8   SubqueryNode           1     - LET c0 = ...   /* const subquery */
  2   SingletonNode          1       * ROOT
 40   IndexNode              1         - FOR attr IN products_attributes   /* persistent index scan */
  6   CalculationNode        1           - LET #21 = attr.`productId`   /* attribute expression */   /* collections used: attr : products_attributes */
  7   ReturnNode             1           - RETURN #21
 15   SubqueryNode           1     - LET c1 = ...   /* const subquery */
  9   SingletonNode          1       * ROOT
 41   IndexNode              0         - FOR attr IN products_attributes   /* persistent index scan */
 13   CalculationNode        0           - LET #25 = attr.`productId`   /* attribute expression */   /* collections used: attr : products_attributes */
 14   ReturnNode             0           - RETURN #25
 22   SubqueryNode           1     - LET c2 = ...   /* const subquery */
 16   SingletonNode          1       * ROOT
 42   IndexNode              0         - FOR attr IN products_attributes   /* persistent index scan */
 20   CalculationNode        0           - LET #29 = attr.`productId`   /* attribute expression */   /* collections used: attr : products_attributes */
 21   ReturnNode             0           - RETURN #29
 29   SubqueryNode           1     - LET c3 = ...   /* const subquery */
 23   SingletonNode          1       * ROOT
 43   IndexNode              0         - FOR attr IN products_attributes   /* persistent index scan */
 27   CalculationNode        0           - LET #33 = attr.`productId`   /* attribute expression */   /* collections used: attr : products_attributes */
 28   ReturnNode             0           - RETURN #33
 30   CalculationNode        1     - LET collections = INTERSECTION(c0, c1, c2, c3)   /* simple expression */
 39   IndexNode              1     - FOR p IN products   /* persistent index scan */
 35   CalculationNode        1       - LET #37 = p.`date`   /* attribute expression */   /* collections used: p : products */
 31   EnumerateListNode    100       - FOR pid IN collections   /* list iteration */
 44   CalculationNode      100         - LET #35 = (("product" in p.`st`) && (p.`_key` == pid))   /* simple expression */   /* collections used: p : products */
 34   FilterNode           100         - FILTER #35
 36   SortNode             100         - SORT #37 DESC
 37   LimitNode             10         - LIMIT 0, 10
 38   ReturnNode            10         - RETURN p

Indexes used:
 By   Type         Collection            Unique   Sparse   Selectivity   Fields               Ranges
 40   persistent   products_attributes   true     false            n/a   [ `key`, `value` ]   ((attr.`key` == "nt1") && (attr.`value` >= 0) && (attr.`value` <= 5))
 41   persistent   products_attributes   true     false            n/a   [ `key`, `value` ]   ((attr.`key` == "st1") && (attr.`value` == "test str"))
 42   persistent   products_attributes   true     false            n/a   [ `key`, `value` ]   ((attr.`key` == "mlt1") && (attr.`value` == "mo1"))
 43   persistent   products_attributes   true     false            n/a   [ `key`, `value` ]   ((attr.`key` == "mlt1") && (attr.`value` == "mo2"))
 39   persistent   products              false    false            n/a   [ `st[*]` ]          ("test" in p.`st`)

Optimization rules applied:
 Id   RuleName
  1   move-calculations-up
  2   move-filters-up
  3   interchange-adjacent-enumerations
  4   move-calculations-up-2
  5   move-filters-up-2
  6   use-indexes
  7   remove-filter-covered-by-index
  8   remove-unnecessary-calculations-2


If you need an intersection, then you could simply combine the subqueries into a single with four FILTER clauses, which act like a natural AND .如果您需要一个交集,那么您可以简单地将子查询组合成一个带有四个FILTER子句的单个子查询,这就像一个自然的AND

LET collections = (
    FOR attr IN products_attributes
        FILTER attr.key == "nt1" AND attr.value >= 0 AND attr.value <= 5
        FILTER attr.key == "st1" AND attr.value == "test str"
        FILTER attr.key == "mlt1" AND attr.value == "mo1"
        FILTER attr.key == "mlt1" AND attr.value == "mo2"
        RETURN attr.productId
)

You might have to create an index with all of those columns, but it should work.您可能必须为所有这些列创建一个索引,但它应该可以工作。 Otherwise, you could reduce subsequent datasets by limiting based on the previous.否则,您可以通过基于先前的限制来减少后续数据集。 This is especially useful if the search crosses collections or indexing is not possible/rational:如果搜索跨越 collections 或索引不可能/合理,这将特别有用:

LET c0 = (
    FOR attr IN products_attributes
        FILTER attr.key == "nt1" AND attr.value >= 0 AND attr.value <= 5
        RETURN attr.productId
)
LET c1 = (
    FOR attr IN products_attributes
        FILTER attr.productId in c0
        FILTER attr.key == "st1" AND attr.value == "test str"
        RETURN attr.productId
)
LET c2 = (
    FOR attr IN products_attributes
        FILTER attr.productId in c1
        FILTER attr.key == "mlt1" AND attr.value == "mo1"
        RETURN attr.productId
)
LET c3 = (
    FOR attr IN products_attributes
        FILTER attr.productId in c2
        FILTER attr.key == "mlt1" AND attr.value == "mo2"
        RETURN attr.productId
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM