将n个节点连接到单个节点的最佳方法是什么?

时间:2017-04-18 19:14:01

标签: database-design neo4j architecture orientdb graph-databases

我正在为我正在构建的应用程序建模图形,其中 n用户连接到n个用户,我还有 n帖子,可以< strong> n用户喜欢。所以对于给定的用户,结构看起来像这样, enter image description here

如果用户喜欢数百个Post节点,它将为节点生成100个边(realtionships),当post为n时,边也将为n。 所以一个用户将连接到n个用户和n个帖子以及n个未来的节点类型。

因此,使用中间节点从而减少了给定节点的边缘,这看起来像这样,

enter image description here

如果用户有一个名为Collection的中间节点,它将连接到喜欢,因为这是一个属性图,我可以向中间节点添加一个属性,使其行为类似于来自用户的连接(类似于,Likes.username = User.username)

这与此问题类似(Graph database modelling: Should i use a collection node to avoid to many rel on a node

我的想法是

这种中间连接节点可以将垃圾与主节点隔离开来,从而加快自定义算法的速度。

我的问题,

  1. 缩放的最佳解决方案是什么?
  2. 为什么我要考虑这个解决方案呢?

2 个答案:

答案 0 :(得分:8)

这种解决方案有利有弊。

主要缺点是遍历操作会更昂贵,即。在找到帖子之前,你必须再遍历一个节点。

优势如下:

  • 当您添加新的&#34;喜欢&#34;时,用户节点上的争用减少,即。用户@version不会增加,因此您可以在并发中对User进行更新,而不会出现版本冲突
  • 向&#34;喜欢&#34;添加信息的能力节点。你也可以单独使用边缘,但你必须复制所有边缘的信息。
  • 一个较小的用户,特别是在嵌入式/树状ridbag阈值之下http://orientdb.com/docs/2.2.x/RidBag.html只要考虑到使用二进制协议,当你有一个树RidBag时,它不会立即被序列化到客户端,但是你将有一个迭代器,因此获取单个用户的开销不会很大。另一方面,使用HTTP协议,您将收到带顶点的所有边缘RID,因此在这种情况下,您将使用第二种方法节省大量带宽和计算时间。

关于您的问题,最佳解决方案是更适合您的工作负载的解决方案:如果您对用户进行了大量更新,第二种解决方案将为您带来直接优势;如果您经常单独取用用户,第二种解决方案也会带来优势;另一方面,如果您的主要关注点是快速遍历,那么第二种解决方案将非常适合。

答案 1 :(得分:6)

根据非常好的书“学习Neo4j”(Rik Van Bruggen,可用于download in the Neo4j's web site),您的问题被称为“密集节点”或“超级节点”:连接太多的节点。

仍然根据这本书,超节点

  

“成为图遍历的真正问题,因为图表   数据库管理系统将不得不评估所有连接的   与该节点的关系,以确定下一步   将在图表遍历中。“

Rik提出的解决方案非常接近您的解决方案(添加中间节点):它包括在用户和您喜欢的帖子之间添加“元”节点。这个元节点最多应该有一百个连接。如果当前元节点达到100个连接,则必须创建一个新的元节点并将其添加到层次结构中,根据图中的示例,显示一个受欢迎的艺术家和粉丝的示例:

Dense node

Neo4j团队一直在努力提高超级节点的性能,例如在this Github commit(例如)中可以看到,它改变了节点的关系如何存储在磁盘上,在链表中结构

我认为最好的方法是让您的图表模型尽可能简单。您还没有密集节点问题,而过早优化可能会为您的模型增加一些不必要的复杂性。如果将来密集节点成为问题,您可以更准确地更改模型。简单起初是个不错的选择。

您可以在以下链接中阅读有关图数据库中超级节点的更多信息: