在数据库中存储有关无向图边的数据

时间:2013-05-13 09:44:57

标签: sql hash graph

我的数据结构是一个带有节点和边的无向图(可能是密集的)。节点I和J之间的边缘将具有与之关联的附加数据,并且我希望能够在查询时唯一地识别该边缘并且能够快速确定I和J之间的边缘是否存在

我决定使用两个表来完成此任务:

Table Nodes
-----------
node_id PK
...
(additional fields)


Table Edges
-----------
nodes_hash(node_id, node_id) PK
edge_thickness
...
(additional fields)

其中每个边的主键将由一个带有两个节点ID的散列函数nodes_hash(node_id, node_id)计算。

我的问题:

  • 我如何提出一个好的哈希函数来计算边缘ID?
  • 我可能会忽视这种方法的任何主要缺点吗?

2 个答案:

答案 0 :(得分:2)

你没有理由需要将边缘编码为哈希:确保没有重复是一个简单的唯一约束。

虽然有计算哈希的方法(创建路径枚举字符串,并计算其MD5哈希或沿着这些行的某些东西),但是存储哈希没有价值,也没有使用路径枚举方案来存储图表数据本身。路径枚举的工作方式与文件系统中的完全相同,存储类似/a/b/c(如果按节点ID枚举)或1.2.1.5(如果按边序列枚举)。

对于您的特定用例,我将使用公共邻接列表表设置(除非树中的其他操作调用更专业的数据结构,例如节点集或路径/边缘枚举)。在此结构中,顶级节点具有PARENT_ID = NULL

CREATE TABLE NODES(
  NODE_ID INT NOT NULL,
  -- OTHER NODE ATTRIBUTES
  PRIMARY KEY (NODE_ID)
);

CREATE TABLE EDGES(
  NODE_ID INT NOT NULL,
  PARENT_ID INT,
  EDGE_WEIGHT INT NOT NULL,
  -- OTHER EDGE ATTRIBUTES
  FOREIGN KEY (NODE_ID) REFERENCES NODES(NODE_ID), 
  FOREIGN KEY (PARENT_ID) REFERENCES NODES(NODE_ID),
  CHECK (PARENT_ID <> NODE_ID),                   -- This avoids simple cycles
  CONSTRAINT UNIQ_EDGE UNIQUE (NODE_ID,PARENT_ID) -- This avoids duplicate edges
);

答案 1 :(得分:0)

为什么要使用哈希函数来生成这样的密钥?

我会为节点提供一个整数主键(节点ID)。

我会有一个边的整数主键(边ID)。

然后,我会在边缘表中为每个节点添加两列,并使用外键关系返回节点表。

我可以很容易地想到使用哈希函数的两个缺点。首先,你可能会发生碰撞。事实上,如果所有内容都存储为整数,那么 只会根据鸽子原则进行碰撞。

其次,无论如何都需要存储节点ID。几乎我能想到的任何图形问题都需要知道边缘连接的节点。

您将处理无向图是以下约束/触发器:

(1)添加一个约束/触发器node1&lt;节点2(或者&lt; =如果允许自连接)。

(2)在node1,node2上添加唯一索引。

(3)添加一个插入前触发器,以确保对于任意值,node1获得较小的值,node2获得较大的值。

在Oracle中,您可以通过在最少(node1,node2)和最大(node1,node)上使用基于函数的索引来组合这些。