首页 > 解决方案 > 为什么 allshortestpath 这么慢?

问题描述

我用 python 和 neo4j 库创建了一些图形数据库。图有 50k 个节点和 100k 个关系。

如何创建节点:

CREATE (user:user {task_id: %s, id: %s, root: 1, private: 0})

如何建立关系:

 MATCH (root_user), (friend_user) WHERE root_user.id = %s
                                  AND root_user.task_id = %s  
                                  AND friend_user.id = %s
                                  AND friend_user.task_id = %s
                    CREATE (root_user)-[r: FRIEND_OF]->(friend_user) RETURN root_user, friend_user 

我如何搜索节点之间的所有路径:

MATCH (start_user:user {id: %s, task_id: %s}), 
      (end_user:user {id: %s, task_id: %s}), 
      path = allShortestPaths((start_user)-[*..3]-(end_user)) RETURN path

Soo 非常慢,在 50k 图表上大约需要 30-60 分钟。我不明白为什么。我尝试像这样创建索引:

CREATE INDEX ON :user(id, task_id)

但它没有帮助。你能帮助我吗?谢谢。

标签: pythonneo4jcypher

解决方案


你永远不应该生成一个长的 Cypher 查询,其中包含本质上相同的 Cypher 代码的 N 个细微变化。这非常慢并且占用大量内存。

相反,您应该将参数传递给更简单的 Cypher 查询。

例如,在创建节点时,您可以将data参数传递给以下 Cypher 代码:

UNWIND $data AS d
CREATE (user:user {task_id: d.taskId, id: d.id, root: 1, private: 0})

您传递的data参数值将是一个映射列表,每个映射将包含一个taskIdid。该UNWIND子句将data列表“展开”为单独的d地图。这会快得多。

需要对您的关系创建代码执行类似的操作。

此外,为了使用您的任何:user索引,您的MATCH子句必须:user在相关节点模式中指定标签。否则,您要求 Cypher 扫描所有节点,而不考虑标签,并且这种处理将无法利用索引。例如,相关查询应以:

MATCH (root_user:user), (friend_user:user)
...

推荐阅读