【发布时间】:2020-04-14 21:55:00
【问题描述】:
我正在尝试弄清楚 neo4j 使用哪种图形算法/哪种类型的图形结构。
它具有定向和标记的边缘。也可以在节点和边中存储属性。
【问题讨论】:
标签: algorithm data-structures neo4j graph-algorithm graph-databases
我正在尝试弄清楚 neo4j 使用哪种图形算法/哪种类型的图形结构。
它具有定向和标记的边缘。也可以在节点和边中存储属性。
【问题讨论】:
标签: algorithm data-structures neo4j graph-algorithm graph-databases
Neo4j 是labeled property graph。
对于物理结构,我们有事物的存储:节点存储、关系存储、属性存储、标签存储、字符串存储等。
这些只是固定格式的多个条目的文件,因此图形存储中的每个条目具有相同的格式,关系存储中的每个条目具有相同的格式等,并且条目之间存在指针(图形 ID) .因此,graph ids 实际上是用于在 store 中链接元素和相关元素之间进行指针跳跃的偏移量。
从逻辑上讲,节点存储中的节点条目具有指向其他存储中其他条目的各种指针,例如它的标签,以及关系链中的第一个关系。关系具有指向关系的开始和结束节点以及链中的上一个和下一个关系的指针。并且节点和关系都有指向第一个属性条目的指针,该条目构成了它们的属性链的开始。
所以从逻辑上讲,我们有等价的链表结构连接我们的一些元素(每个节点的属性链,每个节点的关系链)。但是对于节点之间通过关系的连接,在对图形进行建模时在白板上绘制的内容是对结构中正在发生的事情的一个很好的近似,节点和关系直接相互链接,指向彼此在相关商店中的条目文件。
我们确实有一些冗余来加快查找速度...节点在节点条目本身中保存一些标签,并且关系保存它们的类型。
这也是最简单的抽象,我们在密集节点上使用的格式确实略有不同,因此我们根据类型和方向在节点上存储关系,从而允许通过我们正在寻找的内容快速选择相关关系,而不是而不是必须考虑和过滤所有存在的关系。
这是对物理结构的高级概述。更有趣的是为什么选择这种结构,它允许什么,以及这些因素如何影响原生图形数据库与关系数据库在图形和大量遍历用例方面的竞争力。
所有这一切的重点是关系遍历不使用表连接或它们的等价物。遍历关系/模式的成本不是基于图中的总关系或节点,而仅基于存在的实际关系和节点,存储之间的 O(1) 指针跳跃,节点 -> rel -> 节点等。
这是称为index-free adjacency 的原生图形数据库的一个特征,并且由我们使用的存储格式启用。这是主要原因之一,对于图形用例和连接的数据,您会考虑在关系数据库上使用本机图形数据库(或在非本机图形数据库或仅位于关系数据库之上的覆盖)。
所以举个例子,如果我们在节点 1 与其他节点有 3 个关系,并且图中有 100 亿个节点和 500 亿个关系,那么遍历到模式中的下一个节点将会非常快。总共有多少关系或节点并不重要,重要的是从当前节点开始,只有 3 个关系存在,所以我们做了三个 O(1) 指针跳跃(以及任何过滤)并继续从那些三个节点试图找到适合模式的路径。遍历的成本与您最终接触/遍历的图表的任何部分成正比,而不是与图表的总大小成正比。
当然,要创建关系,您通常必须做相当于表连接的操作...通过某些属性匹配节点(通常使用用于在图中查找入口点的索引结构),然后创建它们之间的关系他们。
所以是的,索引查找确实发挥了作用,但这些发生在关系创建期间。一旦创建了关系,对它们的查询就变成了 O(1) 每次遍历、指针跳跃以及您想要执行的任何额外过滤的成本。我们抵消了关系创建的连接成本,从而优化了运行时遍历速度。
剩余的索引用于在图中查找入口点,一旦我们有了这些入口点,遍历就会成为焦点,我们再次只是指针跳跃,没有依赖于数据大小的表连接。
我的一位同事 Max De Marzi includes a description and visualization of the store format 的一篇较早的博客文章可能会有所帮助。它在某些方面有点过时(博客条目和从中链接的视频都是 2012 年的),我们一直在寻找优化和调整商店格式以提高性能的方法,但该条目的精神是什么事项:
关系有点像显式表连接,但我们在关系创建而不是遍历上支付成本。对于遍历,我们只是指针跳跃,并且不会随着数据的增长而减慢,就像关系数据库中的表连接一样。
【讨论】: