我考虑过创建一个Vertices表和一个Edges表但是会在内存中构建图形并遍历子图需要大量的查找吗?我想避免过多的数据库读取。有没有其他方法可以持久保存图表?
旁注:我听说过Neo4j,但我的问题是如何在概念上代表标准数据库中的图形。我对mongodb等NoSQL解决方案持开放态度。
答案 0 :(得分:26)
遗憾的是答案:你的考虑在每个方面都是完全正确的。您必须将节点(顶点)存储在一个表中,并且Edges引用FromNode和ToNode以将图形数据结构转换为关系数据结构。你也是对的,这最终会导致大量的查找,因为你无法将它分成子图,可能会立即查询。您必须从节点遍历到边缘到节点到边缘到节点...依此类推(递归,而SQL正在使用集合)。
重点是......
关系,面向图,面向对象,基于文档是满足不同要求的不同类型的数据结构。这就是它的全部内容以及为什么这么多不同的NoSQL数据库(大多数都是简单的文档存储)出现了,因为以关系方式组织大数据毫无意义。
备选方案1 - 面向图形的数据库
但也有一些面向图形的NoSQL数据库,这使得图形数据模型成为像OrientDB这样的一流公民,我现在正在玩一点点。关于它的好处是,虽然它将数据保存为图形,但它仍然可以以关系或甚至面向对象或面向文档的方式使用(即通过查询普通的旧SQL)。尽管如此,Traversing the graph是获取数据的最佳方式。
备选方案2 - 使用内存中的图表
在快速路由方面,像Graphhopper这样的路由框架在内存中构建了完整的图形(数十亿个节点)。因为Graphhopper使用其GraphStore的MemoryMapped实现,甚至可以在仅需要一些MB内存的Android设备上运行。完整的图形在启动时从数据库读入存储器,然后在那里完成路由,因此您无需查找数据库。
答案 1 :(得分:4)
我遇到了同样的问题,并决定最终采用以下结构,这需要2个数据库查询,然后其余工作在内存中:
将节点存储在表中,并使用每个节点记录引用该图:
Table Nodes
id | title | graph_id
---------------------
105 | node1 | 2
106 | node2 | 2
还将边存储在另一个表中,并再次引用这些边所属的图形与每条边:
Table Edges
id | from_node_id | to_node_id | graph_id
-----------------------------------------
1 | 105 | 106 | 2
2 | 106 | 105 | 2
使用一个查询获取所有节点,然后使用另一个查询获取所有边缘。
现在构建您存储图表的首选方式(例如,邻接列表)并继续您的应用程序流程。
答案 2 :(得分:0)
添加到前面的答案中,MS SQL Server添加了support for Graph Architecture starting with 2017。
它遵循所描述的具有 Node 和 Edges 表(应使用特殊的“ AS NODE”和“ AS EDGE”关键字创建)表的模式。
它还引入了新的MATCH关键字,“以支持通过图形进行模式匹配和遍历”(在下面的示例中,朋友是 edge 表的名称):
SELECT Person2.name AS FriendName
FROM Person Person1, friend, Person Person2
WHERE MATCH(Person1-(friend)->Person2)
AND Person1.name = 'Alice';
还有一组非常好的文章on SQL Server Graph Databases on redgate Hub。