【翻译自:https://neo4j.com/developer/kb/fast-counts-using-the-count-store/】
【由Neo4j APAC授权编译发布】
Neo4j维护计数存储文件,用于保存许多对象的统计元数据。
计数存储用于通知查询计划器,让它能够在查询规划时做出明智的选择。
从计数存储获取统计数据的时间固定,您从计数存储获得某个对象的统计信息非常快速。
通过 EXPLAIN 查询,我们可以从查询计划中判断查询是否使用了计数存储,若使用则可看到 NodeCountFromCountStore 或 RelationshipCountFromCountStore 操作符。
1、计数存储查询的限制
根据定义,使用计数查询必须存在 count() 聚合。
WHERE 条件句不能使用,匹配模式中也不能有任何属性。
由于查询计划器的限制,count() 仅在 WITH 或 RETURN 上单独进行聚合时,才会使用计数存储。
【限制–如果count()聚合范围内还有其它变量,则不会使用计数存储。】
如前所述,通过查看查询计划中是否存在 NodeCountFromCountStore 或 RelationshipCountFromCountStore,来判断计数存储是否被使用。
文末我们将讨论在同一查询中返回多个计数时的解决方法。
2、节点统计
您可以使用计数存储来获取数据库中所有节点的计数:
MATCH (n)
RETURN count(n) as count
您还可以获取某一标签所有节点的计数:
MATCH (n:Person)
RETURN count(n) as count
这些查询中变量可选,您可以忽略它们,使用count(*)可得到相同结果:
MATCH ()
RETURN count(*) as count
和
MATCH (:Person)
RETURN count(*) as count
【限制–无法使用计数存储来查询多个标签的节点。】
查询多标签节点将不使用计数存储,因为这些数据未在计数存储中保存。
下面的查询将不使用计数存储:
MATCH (n:Person:Director)
RETURN count(n) as count
3、关系计数
计数存储还保存关系的计数元数据,所用模式必须描述单一关系。注意,查询在匹配模式中 必须 使用有向关系 才能 使用计数存储,请不要忽略方向。
无论是否存在关系类型,都将使用计数存储:
MATCH ()-[r]->()
RETURN count(r) as count
MATCH ()-[r:ACTED_IN]->()
RETURN count(r) as count
查询多种类型的关系时,计数存储依然会被使用,对每种类型的关系计数进行累加:
MATCH ()-[r:ACTED_IN|DIRECTED]->()
RETURN count(r) as count
与节点一样,变量可选,count(*)可以代替使用:
MATCH ()-[:ACTED_IN]->()
RETURN count(*) as count
4、TO/FROM单个标签节点的关系计数
计数存储也保存了每一标签为结束节点的关系计数。以下查询将从计数存储中获取其统计数据。
MATCH ()-[r:ACTED_IN]->(:Movie)
RETURN count(r) as countMATCH (:Person)-[r:ACTED_IN]->()
RETURN count(r) as countMATCH ()-[r]->(:Movie)
RETURN count(r) as count
【限制–开始节点和结束节点的标签都存在时不能使用计数存储。】
计数存储不保存开始节点和结束节点同时存在标签的元数据。
下面的查询将不使用计数存储:
MATCH (:Person)-[r:ACTED_IN]->(:Movie)
RETURN count(r) as count
5、单个查询获取多个计数
如果您想在单个查询中从计数存储获取多个计数,则可能会遇到前文提到的限制:必须在 WITH 或 RETURN 子句中单独使用 count() 聚合。
5.1 计数查询使用UNION ALL
如果我们对不同查询使用计数存储来获得计数,UNION 合并,很方便即可获得所需的计数:
MATCH (n:Person)
WITH count(n) as count
RETURN 'Person' as label, count
UNION ALL
MATCH (n:Movie)
WITH count(n) as count
RETURN 'Movie' as label, count
注意,如果我们需要另一变量来提供上下文,该变量只能在获得 count() 后才能引入,因为聚合处的其它变量会阻止使用计数存储。
另外,我们可以返回 map 结构数据,包括标签类型及其相关计数:
MATCH (n:Person)
RETURN {label:'Person', count: count(n)} as info
UNION ALL
MATCH (n:Movie)
RETURN {label:'Movie', count: count(n)} as info
5.2 使用apoc.cypher.run()动态获取每个标签/类型的计数
apoc.cypher.run() 用于每次执行一个 Cypher 查询,可以让您从每次的计数存储中获取计数。
通过调用节点标签或关系类型,可以高效便捷的同时获取多个计数:
对于标签:
CALL db.labels() YIELD label
CALL apoc.cypher.run('MATCH (:`'+label+'`) RETURN count(*) as count',{}) YIELD value
RETURN label, value.count
对于关系:
CALL db.relationshipTypes() YIELD relationshipType as type
CALL apoc.cypher.run('MATCH ()-[:`'+type+'`]->() RETURN count(*) as count',{}) YIELD value
RETURN type, value.count
5.3 使用APOC过程apoc.meta.stats()
APOC Procedures 有 meta procedures,可用于访问几乎所有计数存储数据。
您可以通过 CALL apoc.meta.stats() ,选择要显示的数据。
5.3.1 内容
调用 apoc.meta.stats() 将返回以下值:
labelCount – 图中标签数
relTypeCount – 图中关系类型数
propertyKeyCount – 图中属性键数量
nodeCount – 图中节点数
relCount – 图中关系数
Labels – 每种标签的映射及该标签的计数
relTypes – 每种关系模式的映射,包含关系类型、每种标签作为结束节点的模式及相关的计数
relTypesCount – 每种关系类型的映射及该类型的计数
stats –包含上述所有计数的映射
5.3.2 用法
labels 计数通常最有用,类似方法可以用于其它:
CALL apoc.meta.stats() YIELD labels
RETURN labels
返回如下映射:
{
"Movie": 38,
"Word": 12,
"News": 2,
"Director": 28,
"Reviewer": 3,
"Person": 133,
"Sentence": 17
}
获取其中一个值,就像使用“.”获取键值一样容易。
CALL apoc.meta.stats() YIELD labels
RETURN labels.Person as personCount
如果需要多个值,我们可以使用以下查询:
CALL apoc.meta.stats() YIELD labels
RETURN labels {.Person, .Movie, .Director} as counts
更多技术咨询:
yusonglin@we-yun.com
网友评论