GraphGists

我们将从一个基本示例开始,帮助您掌握查询分析(Profiling)。以下示例将使用电影数据集。

让我们首先导入数据

LOAD CSV WITH HEADERS FROM "https://raw.githubusercontent.com/neo4j/neo4j/2.3/manual/cypher/cypher-docs/src/docs/graphgists/query-tuning/movies.csv" AS line
MERGE (m:Movie {title:line.title})
ON CREATE SET m.released = toInteger(line.released), m.tagline = line.tagline
LOAD CSV WITH HEADERS FROM 'https://raw.githubusercontent.com/neo4j/neo4j/2.3/manual/cypher/cypher-docs/src/docs/graphgists/query-tuning/actors.csv' AS line

MATCH (m:Movie {title:line.title})
MERGE (p:Person {name:line.name})
ON CREATE SET p.born = toInteger(line.born)

MERGE (p)-[:ACTED_IN {roles:split(line.roles,";")}]->(m)
LOAD CSV WITH HEADERS FROM 'https://raw.githubusercontent.com/neo4j/neo4j/2.3/manual/cypher/cypher-docs/src/docs/graphgists/query-tuning/directors.csv' AS line
MATCH (m:Movie {title:line.title})
MERGE (p:Person {name:line.name})
ON CREATE SET p.born = toInteger(line.born)

MERGE (p)-[:DIRECTED]->(m)

查找汤姆·汉克斯:朴素方法

假设我们要编写一个查询来查找汤姆·汉克斯。朴素的方法如下所示:

MATCH (p {name:"Tom Hanks"})
RETURN p

此查询将找到汤姆·汉克斯节点,但随着数据库中节点数量的增加,它将变得越来越慢。

分析

我们可以对查询进行分析,找出此查询为何如此缓慢的原因。

PROFILE MATCH (p {name:"Tom Hanks"})
RETURN p

阅读执行计划时首先要记住的是,您需要从下往上阅读。

循此思路,从最后一行开始,我们首先注意到 Rows 列中的值似乎很高,考虑到数据库中只有一个名称属性为 Tom Hanks 的节点。如果看 Operator 列,我们会发现使用了 AllNodesScan,这意味着查询计划器扫描了数据库中的所有节点。

向上看前一行,我们看到 Filter 运算符,它将检查 AllNodesScan 传递的每个节点的 name 属性。

鉴于我们正在查看许多甚至不是人的节点,因此这似乎是查找 Tom Hanks 的一种低效方法,因为这些节点不是我们要查找的内容。

查找汤姆·汉克斯:第二次尝试

每当我们查找节点时,都应指定标签以帮助查询计划器缩小搜索范围。对于此查询,我们需要添加一个 Person 标签。

MATCH (p:Person {name:"Tom Hanks"})
RETURN p

此查询将比第一个查询更快,但随着数据库中人数的增加,我们再次注意到查询速度变慢了。

分析

同样,我们可以对查询进行分析,找出我们的查询仍然有些缓慢的原因

PROFILE MATCH (p:Person {name:"Tom Hanks"})
RETURN p

这次最后一行 Rows 的值减小了,因此我们不再扫描之前扫描的一些节点,这是一个好的开始。NodeByLabelScan 运算符表明我们首先对数据库中的所有 Person 节点进行了线性扫描,从而实现了这一点。

完成此操作后,我们再次使用 Filter 运算符扫描所有这些节点,比较每个节点的 name 属性。

在某些情况下,这可能是可以接受的,但如果我们经常按名称查找人物,那么如果在 Person 标签的 name 属性上创建索引,性能会更好。

CREATE INDEX ON :Person(name)

查找汤姆·汉克斯:对 Person 创建索引

现在如果我们再次运行查询,它将运行得更快

MATCH (p:Person {name:"Tom Hanks"})
RETURN p

分析

让我们分析查询,看看为什么这个版本快得多

PROFILE MATCH (p:Person {name:"Tom Hanks"})
RETURN p

我们的执行计划缩减到一行,并使用了 Node Index Seek 运算符,该运算符执行模式索引查找以找到适当的节点。