GraphGists

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

让我们从导入数据开始

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操作符,该操作符执行模式索引查找以找到适当的节点。