我很好奇过滤器在 neo4j 查询中是如何工作的。它们会导致数据库命中(根据 PROFILE),而且它们似乎不应该命中。
查询示例:
PROFILE MATCH (a:act)<-[r:relationship]-(n)
WHERE a.chapter='13' and a.year='2009'
RETURN r, n
- NodeIndexSeek:(我在标签
act
上为chapter
属性创建了一个索引)返回 6 行。 - 过滤器:
a.year == {AUTOSTRING1}
导致 12 次数据库命中。
如果它已经在早期的数据库读取中获取了 a
的 6 个匹配实例,为什么它需要进行任何数据库命中,难道它不应该只是过滤掉它们而不返回进行更多的数据库读取吗?
我意识到我在这里将“数据库命中”等同于“数据库读取”,这可能不准确。如果不是,“db hits”到底是什么?
最后,过滤器产生的数据库命中数似乎大致匹配:
<number of filtering elements> * 2 * <number of already queried nodes to filter on>
其中'number of filtering elements'是提供的过滤器的数量,即
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)<-[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
EXPLAIN MATCH (a:act)<-[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: ?
最佳答案
因为读取节点(记录)和读取属性(记录)不是同一个数据库操作。
您说得对,过滤器匹配项最多应为 6。 通常 Neo4j 将过滤器和谓词拉到尽可能早的时刻,因此它应该在索引查找之后直接进行过滤。
虽然在某些情况下(由于谓词)它只能在找到路径后进行过滤,然后 db-hits 的数量可能等于检查路径的数量。
您使用的是哪个 Neo4j 版本?你能分享你的完整查询计划吗?
关于neo4j - 分析 neo4j 查询 : filter to db hits,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31787514/