Neo4J 使用关系属性来加快查找速度?
Neo4J using properties on relationships for quicker lookup?
我还在尝试使用 neo4j 来执行复杂的查询(类似于最短路径搜索,除了我将非常奇怪的条件应用于此搜索,例如根据遍历节点数计算的最小路径长度)。
我的数据集包含大约 250 万个单一类型的节点和大约 15 亿条边(也是单一类型)。每个给定节点与 "next" 节点平均有 1000 个方向关系。
然而,我有一个查询允许我在给定所有条件的情况下检索这条最短路径,但我发现具有适当响应时间(不到一秒)的唯一方法是实际限制每个结果后的数量将新节点添加到路径中,对其进行过滤、排序,然后追踪到下一个节点(我想这是一种贪心算法)。
我想将它们限制得比我少得多,以便产生更多的路径,但问题是这种搜索的指数复杂性使得从 LIMIT 40
到 LIMIT 60
通常是 x10 ~ x100 的处理时间。
话虽如此,我仍在评估几种解决方案以提高请求速度,但我不确定它们会产生什么结果,因为我不确定 neo4j 在内部如何真正存储我的数据。
我考虑的解决方案实际上是在我的关系中添加一个 属性,它是 1 到 15 之间的整数,因为我通常只会查询具有一个或两个最大不同值的关系为此 属性。 (例如,只有具有此 属性 到 8 或 9 的关系)。
正如我所猜测的那样,对于每个关系,neo4j 必须收集原始节点属性并使用它来应用我的进一步过滤器,这在跨越 4 个节点长路径时需要很长时间,每个节点有 1000 个关系(我猜测 O(1000^4))。我说得对吗?
有了关系属性,它是否可以直接访问它而无需进一步获取数据?它有可能使我的查询更快吗? Neo4j 边缘属性是如何存储的?
更新
按照@logisima 的建议,我直接用neo4j 的Java 遍历API 编写了一个程序。然后我切换到 Neo4J 的原始 Java 过程 API 以根据我的用例需要利用更多的功能和灵活性。
结果非常好:下限复杂性总体上比以前少了一点,但上限快了十倍,而且至少有一些将用于遍历的节点在Neo4j 的缓存,性能变得惊人(我的一个测试在不到一秒的时间内深度为 20,而我通常只需要深度 4)。
但这还不是全部。这些程序使其非常容易定制,同时保持最佳性能并优化每一个操作。结果是我可以在更少的计算时间内使用更强大的过滤器,并且可以轻松地更新我的程序以添加新功能。最后但并非最不重要的一点是,程序可以很容易地插入 neo4j 的 spring-data(我用它来将 neo4j 连接到我的 HTTP API)。与 cypher 一样,我将不得不自动生成查询(因为非常复杂,有 30 java 类 来正确地完成这个技巧)并且我应该使用 jdbc neo4j 同时只为这个请求处理一个单独的连接池。不能推荐更多使用很棒的 neo4j java API.
再次感谢@logisima
如果你想做一个自定义短路径算法,那么你应该写一个cypher procedure with the traversal API.
Cypher 的原理是pattern matching
,你想以特定的方式遍历图来找到你的好解。
对于您的用例,响应时间应该更快!
我还在尝试使用 neo4j 来执行复杂的查询(类似于最短路径搜索,除了我将非常奇怪的条件应用于此搜索,例如根据遍历节点数计算的最小路径长度)。
我的数据集包含大约 250 万个单一类型的节点和大约 15 亿条边(也是单一类型)。每个给定节点与 "next" 节点平均有 1000 个方向关系。
然而,我有一个查询允许我在给定所有条件的情况下检索这条最短路径,但我发现具有适当响应时间(不到一秒)的唯一方法是实际限制每个结果后的数量将新节点添加到路径中,对其进行过滤、排序,然后追踪到下一个节点(我想这是一种贪心算法)。
我想将它们限制得比我少得多,以便产生更多的路径,但问题是这种搜索的指数复杂性使得从 LIMIT 40
到 LIMIT 60
通常是 x10 ~ x100 的处理时间。
话虽如此,我仍在评估几种解决方案以提高请求速度,但我不确定它们会产生什么结果,因为我不确定 neo4j 在内部如何真正存储我的数据。
我考虑的解决方案实际上是在我的关系中添加一个 属性,它是 1 到 15 之间的整数,因为我通常只会查询具有一个或两个最大不同值的关系为此 属性。 (例如,只有具有此 属性 到 8 或 9 的关系)。
正如我所猜测的那样,对于每个关系,neo4j 必须收集原始节点属性并使用它来应用我的进一步过滤器,这在跨越 4 个节点长路径时需要很长时间,每个节点有 1000 个关系(我猜测 O(1000^4))。我说得对吗?
有了关系属性,它是否可以直接访问它而无需进一步获取数据?它有可能使我的查询更快吗? Neo4j 边缘属性是如何存储的?
更新
按照@logisima 的建议,我直接用neo4j 的Java 遍历API 编写了一个程序。然后我切换到 Neo4J 的原始 Java 过程 API 以根据我的用例需要利用更多的功能和灵活性。
结果非常好:下限复杂性总体上比以前少了一点,但上限快了十倍,而且至少有一些将用于遍历的节点在Neo4j 的缓存,性能变得惊人(我的一个测试在不到一秒的时间内深度为 20,而我通常只需要深度 4)。
但这还不是全部。这些程序使其非常容易定制,同时保持最佳性能并优化每一个操作。结果是我可以在更少的计算时间内使用更强大的过滤器,并且可以轻松地更新我的程序以添加新功能。最后但并非最不重要的一点是,程序可以很容易地插入 neo4j 的 spring-data(我用它来将 neo4j 连接到我的 HTTP API)。与 cypher 一样,我将不得不自动生成查询(因为非常复杂,有 30 java 类 来正确地完成这个技巧)并且我应该使用 jdbc neo4j 同时只为这个请求处理一个单独的连接池。不能推荐更多使用很棒的 neo4j java API.
再次感谢@logisima
如果你想做一个自定义短路径算法,那么你应该写一个cypher procedure with the traversal API.
Cypher 的原理是pattern matching
,你想以特定的方式遍历图来找到你的好解。
对于您的用例,响应时间应该更快!