2015-08-03 66 views
3

我很好奇neo4j查询中的筛选器是如何工作的。他们导致数据库点击(根据PROFILE),似乎他们不应该。分析neo4j查询:筛选到db匹配

示例查询:

PROFILE MATCH (a:act)<-[r:relationship]-(n) 
WHERE a.chapter='13' and a.year='2009' 
RETURN r, n 
  1. NodeIndexSeek:(I创建的索引标签act上为chapter属性)返回6行。
  2. 筛选器:a.year == {AUTOSTRING1}这导致12分贝命中。

为什么它需要做的任何数据库命中,如果它已经获取的a 6匹配情况在早期分贝读,不应该只是过滤下来,而不必回到做多分贝读?

我意识到我在这里将'db命中'和'db reads'等同起来,这可能不准确。如果不是,'db命中'到底是什么?

最后,通过一个过滤器发生分贝的命中数似乎大致匹配:

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

其中“过滤元件的数目”是设置的过滤器的数量,即

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(一个:动作)< - [R:CHILD_OF] - (N) WHERE a.chapter = '13' AND a.year = '2009' RETURN 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 

介绍匹配(一个:动作)< - [R:CHILD_OF] - (N) WHERE a.chapter = '13' AND a.year = '2009' RETURN 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

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

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

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

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

+0

按查询计划我假设你的意思是PROFILE&EXPLAIN?我已将这些添加到我的帖子中。谢谢你的帮助。 – RedCraig

+0

>你是对的,过滤器的命中应该是至多6但。
它看起来像过滤器中使用的每个节点属性都有一个数据库读取,因此在上面的示例中,它为每年比较读取一次节点,并为章节比较读取一次。如果我没有章节的索引,那会是预期的行为吗? – RedCraig