Neo4j使用OR运算符时性能不佳
我使用的是neo4j-3.5社区版。我用neo4j构建了一个巨大的图形,其中包含了大约2000万个电影数据节点。我还插入了类型和关键字,并构建了图表。 以下查询需要>5秒Neo4j使用OR运算符时性能不佳,neo4j,cypher,graph-databases,query-performance,boolean-expression,Neo4j,Cypher,Graph Databases,Query Performance,Boolean Expression,我使用的是neo4j-3.5社区版。我用neo4j构建了一个巨大的图形,其中包含了大约2000万个电影数据节点。我还插入了类型和关键字,并构建了图表。 以下查询需要>5秒 MATCH (p:`Program`), (p:Program)-[genre:of_genre]->(g:Genre), (p:Program)-[key_rel:associated_keyword]->(k:Keyword) WHERE ((g.id IN [
MATCH
(p:`Program`),
(p:Program)-[genre:of_genre]->(g:Genre),
(p:Program)-[key_rel:associated_keyword]->(k:Keyword)
WHERE
((g.id IN [1010]) OR (k.id IN ['keyword_121'])) AND
((p.show_type IN ['movie'])) AND
(p.imdb_score > 0)
RETURN distinct p.id, p.imdb_score
ORDER BY p.imdb_score desc
LIMIT 50
而如果我用AND替换或,则需要<100 ms
MATCH
(p:`Program`),
(p:Program)-[genre:of_genre]->(g:Genre),
(p:Program)-[key_rel:associated_keyword]->(k:Keyword)
WHERE
((g.id IN [1010]) AND (k.id IN ['keyword_121'])) AND
((p.show_type IN ['movie'])) AND
(p.imdb_score > 0)
RETURN distinct p.id, p.imdb_score
ORDER BY p.imdb_score desc
LIMIT 50
在类型id和关键字id上有索引
“或”的配置文件响应:
“和”的配置文件响应:
使用OR运算符编写查询是否有更好的方法?您的查询在3个断开连接的模式之间构建笛卡尔乘积。 请尝试以下查询:
MATCH
(k:Keyword)<-[key_rel:associated_keyword]-(p:Program)-[genre:of_genre]->(g:Genre)
WHERE
((g.id IN [1010]) OR (k.id IN ['keyword_121'])) AND
((p.show_type IN ['movie'])) AND (p.imdb_score > 0)
RETURN distinct p.id, p.imdb_score
ORDER BY p.imdb_score desc
LIMIT 50
匹配
(k:关键词)(g:体裁)
哪里
(g.id在[1010]中)或(k.id在['keyword_121']中)以及
((p.show_键入['movie'])和(p.imdb_得分>0)
返回不同的p.id、p.imdb_分数
按p.imdb_分数说明订购
限制50
您的查询在3个断开连接的模式之间构建笛卡尔乘积。
请尝试以下查询:
MATCH
(k:Keyword)<-[key_rel:associated_keyword]-(p:Program)-[genre:of_genre]->(g:Genre)
WHERE
((g.id IN [1010]) OR (k.id IN ['keyword_121'])) AND
((p.show_type IN ['movie'])) AND (p.imdb_score > 0)
RETURN distinct p.id, p.imdb_score
ORDER BY p.imdb_score desc
LIMIT 50
匹配
(k:关键词)(g:体裁)
哪里
(g.id在[1010]中)或(k.id在['keyword_121']中)以及
((p.show_键入['movie'])和(p.imdb_得分>0)
返回不同的p.id、p.imdb_分数
按p.imdb_分数说明订购
限制50
这可能更适合您:
OPTIONAL MATCH (g:Genre) WHERE g.id IN [1010]
OPTIONAL MATCH (k:Keyword) WHERE k.id IN ['keyword_121']
WITH g, k
MATCH (p:`Program`)
WHERE
p.show_type IN ['movie'] AND
p.imdb_score > 0 AND
((p)-[:of_genre]->(g) OR (p)-[:associated_keyword]->(k))
RETURN distinct p.id, p.imdb_score
ORDER BY p.imdb_score desc
LIMIT 50
此查询可能同时使用这两个索引(或者至少您可以给出使用它们的方法)。此外,如果电影在数据库中不是很常见,您可能需要在:Program(show_type)
上创建索引
WHERE
子句还只是测试是否存在一个所需的:of_genre
或:associated_关键字
关系——它不会尝试实际扫描并在内存中保存所有这些关系。这可能对您更有效:
OPTIONAL MATCH (g:Genre) WHERE g.id IN [1010]
OPTIONAL MATCH (k:Keyword) WHERE k.id IN ['keyword_121']
WITH g, k
MATCH (p:`Program`)
WHERE
p.show_type IN ['movie'] AND
p.imdb_score > 0 AND
((p)-[:of_genre]->(g) OR (p)-[:associated_keyword]->(k))
RETURN distinct p.id, p.imdb_score
ORDER BY p.imdb_score desc
LIMIT 50
此查询可能同时使用这两个索引(或者至少您可以给出使用它们的方法)。此外,如果电影在数据库中不是很常见,您可能需要在:Program(show_type)
上创建索引
WHERE
子句也只是测试是否存在一个所需的:of_genre
或:associated_关键字
关系——它不会尝试实际扫描并在内存中保存所有这些关系。您能在开始时使用配置文件运行查询并在此处共享扩展的计划吗?@Raj:我已经更新了配置文件输出的问题。很难说计划的哪个部分与查询的哪个部分相对应。请首先展开计划的所有元素(查看查询计划时,查询结果窗格右下角的双向下箭头),然后将其添加到问题中,替换您提供的折叠计划。@InverseFalcon:我已更新了查询的计划。您能否在开始时使用PROFILE
运行查询,并在此处共享扩展的计划?@Raj:我已使用PROFILE输出更新了问题。很难判断计划的哪个部分与查询的哪个部分相对应。请首先展开计划的所有元素(查看查询计划时,查询结果窗格右下角的双向下箭头),然后将其添加到问题中,替换您提供的折叠计划。@InverseFalcon:我已经更新了查询计划。这仍然需要与以前类似的时间。@Raj我认为在
中没有必要使用,我们可以使用equals运算符Used,以防需要与多个ID进行匹配。@sravan您可以在没有IN的情况下检查一次吗?@Govind Singh:我必须在中使用运算符。这仍然需要与以前类似的时间。@Raj我认为在
中没有必要使用中的,我们可以使用equals运算符或Used IN,以防需要与多个ID进行匹配。@sravan您可以在不输入的情况下检查一次吗?@Govind Singh:我必须在运算符中使用。此更改不会将性能提高到预期的性能~4秒变为~1.5秒。但是AND查询在100毫秒内执行。您不应该期望性能提高到那个水平。明白简单地改变或改变并不是简单的。它改变了查询必须执行的正确操作的逻辑。它不能只依赖于从k
进行遍历,它必须完成从g
进行遍历的工作,否则,如果使用AND,就不需要这些工作。必须做更多的工作,因为没有其他选择使其逻辑正确。您应该分析cybersam的查询。如果它在k
和g
上使用索引查找,那么它可能是您可以获得的最佳索引。此更改不会将性能提高到预期的性能~4秒变为~1.5秒。但是AND查询在100毫秒内执行。您不应该期望性能提高到那个水平。明白简单地改变或改变并不是简单的。它改变了查询必须执行的正确操作的逻辑。它不能只依赖于从k
进行遍历,它必须完成从g
进行遍历的工作,否则,如果使用AND,就不需要这些工作。必须做更多的工作,因为没有其他选择使其逻辑正确。您应该分析cybersam的查询。如果它在k
和g
上使用索引查找,那么它可能是您能得到的最好结果。