分析neo4j查询:过滤到db命中

时间:2015-08-03 12:39:25

标签: neo4j

我很好奇过滤器在neo4j查询中的工作原理。它们导致db命中(根据PROFILE),似乎他们不应该。

示例查询:

PROFILE MATCH (a:act)<-[r:relationship]-(n)
WHERE a.chapter='13' and a.year='2009'
RETURN r, n
  1. NodeIndexSeek :(我在act属性的标签chapter上创建了一个索引)返回6行。
  2. 过滤:a.year == {AUTOSTRING1}导致12 db命中。
  3. 如果在早期的数据库读取中已经获取了a的6个匹配实例,为什么它需要执行任何数据库命中,不应该只是过滤它们而不需要返回更多db读取?

    我意识到我等同于db命中&#39;用&db;读取&#39;在这里,这可能不准确。如果没有,那么&db; db命中&#39;

    究竟是什么?

    最后,过滤器产生的db命中数似乎大致匹配:

    <number of filtering elements> * 2 * <number of already queried nodes to filter on>
    

    其中&#39;过滤元素的数量&#39;是提供的过滤器数量,即

    WHERE a.year='2009' and a.property_x='thing'
    

    是两个要素。

    感谢您的帮助。

    修改 以下是查询的PROFILE和EXPLAIN的结果。 这只是一个示例查询。我发现了

    的行为
    filter db hits = <number of filtering elements> * 2 * <number of already queried nodes to filter on>
    

    在我查询的查询中通常是正确的。

      

    PROFILE MATCH(a:act)&lt; - [r:CHILD_OF] - (n)   在哪里a.chapter =&#39; 13&#39;和a.year =&#39; 2009&#39;   返回r,n

    8 rows
    55 ms
    
    Compiler CYPHER 2.2
    
    Planner COST
    
    Projection
      |
      +Expand(All)
        |
        +Filter
          |
          +NodeIndexSeek
    
    +---------------+---------------+------+--------+-------------+---------------------------+
    |      Operator | EstimatedRows | Rows | DbHits | Identifiers |                     Other |
    +---------------+---------------+------+--------+-------------+---------------------------+
    |    Projection |             1 |    8 |      0 |     a, n, r |                      r; n |
    |   Expand(All) |             1 |    8 |      9 |     a, n, r |     (a)<-[r:CHILD_OF]-(n) |
    |        Filter |             0 |    1 |     12 |           a | a.year == {  AUTOSTRING1} |
    | NodeIndexSeek |             1 |    6 |      7 |           a |             :act(chapter) |
    +---------------+---------------+------+--------+-------------+---------------------------+
    
    Total database accesses: 28
    
      

    EXPLAIN MATCH(a:act)&lt; - [r:CHILD_OF] - (n)   在哪里a.chapter =&#39; 13&#39;和a.year =&#39; 2009&#39;   返回r,n

    4 ms
    
    Compiler CYPHER 2.2
    
    Planner COST
    
    Projection
      |
      +Expand(All)
        |
        +Filter
          |
          +NodeIndexSeek
    
    +---------------+---------------+-------------+---------------------------+
    |      Operator | EstimatedRows | Identifiers |                     Other |
    +---------------+---------------+-------------+---------------------------+
    |    Projection |             1 |     a, n, r |                      r; n |
    |   Expand(All) |             1 |     a, n, r |     (a)<-[r:CHILD_OF]-(n) |
    |        Filter |             0 |           a | a.year == {  AUTOSTRING1} |
    | NodeIndexSeek |             1 |           a |             :act(chapter) |
    +---------------+---------------+-------------+---------------------------+
    
    Total database accesses: ?
    

1 个答案:

答案 0 :(得分:1)

因为读取节点(记录)和读取属性(记录)不是相同的db操作。

你是对的,过滤器命中应该最多为6。 通常Neo4j会在最早的时刻提取过滤器和谓词,因此它应该在索引查找后直接过滤。

在某些情况下(由于谓词)它只能在找到路径后进行过滤,然后db-hits的数量可能等于检查路径的数量。

您使用的是哪个Neo4j版本?你能分享一下完整的查询计划吗?