在关系数据库中存储树结构的已知方法有哪些?

Ita*_*vka 41 mysql tree design-patterns relational-database

有一个"把FK放到你的父母"的方法,即每个记录指向它的父母.
这是一个难以阅读的操作,但很容易维护.

然后有一个"目录结构键"方法:

0001.0000.0000.0000 main branch 1
0001.0001.0000.0000 child of main branch one
etc
Run Code Online (Sandbox Code Playgroud)

这是超级易读,但难以维护.
有什么其他方式和他们的利弊/专业人士?

Baj*_*aju 51

一如既往:没有最好的解决方案.每种解决方案都会使不同的事情更容易或更难 适合您的解决方案取决于您最常做的操作.

使用parent-id的朴素方法:

优点:

  • 易于实施

  • 很容易将一个大的子树移动到另一个父级

  • 插入很便宜

  • SQL中可直接访问所需的字段

缺点:

  • 检索整棵树是递归的,因此很昂贵

  • 找到所有父母也很昂贵(SQL不知道递归...)

修改的预订树遍历(保存起点和终点):

优点:

  • 检索整棵树很容易且便宜

  • 找到所有父母都很便宜

  • SQL中可直接访问所需的字段

  • 额外奖励:您也在其父节点中保存子节点的顺序

缺点:

  • 插入/更新可能非常昂贵,因为您可能需要更新大量节点

在每个节点中保存路径:

优点:

  • 找到所有父母都很便宜

  • 检索整棵树很便宜

  • 插入很便宜

缺点:

  • 移动整棵树很贵

  • 根据您保存路径的方式,您将无法直接在SQL中使用它,因此如果您想要更改它,您将始终需要获取并解析它.

我更喜欢最后两个中的一个,具体取决于数据更改的频率.

另见:http://media.pragprog.com/titles/bksqla/trees.pdf


TRi*_*RiG 19

修改的预订树遍历

这是一种使用非递归函数(通常是单行SQL)从数据库中检索树的方法,其代价是更新起来有点棘手.

图表显示编号的分层树**

Sitepoint文章的第2部分在数据库中存储分层数据以获取更多详细信息.

  • 文章根本没有忽略这一点.它在第3页明确指出,您必须更新节点编号并让SQL执行此操作. (5认同)
  • 该文章方便地忽略了树必须稍后更新,因此需要重新编号许多节点以保持其一致. (2认同)
  • 应该注意的是,当您的读取次数多于写入次数时,此模型非常有用-如果您期望大量写入操作(例如,每4次读取可能写入1次写入),则此模型可能会出现问题,并且像简单的父ID(和更昂贵的读取)可能会更可取。 (2认同)

Bor*_*lid 5

我会说存储分层数据结构的“黄金方式”是使用分层数据库。例如,HDB。这是一个可以很好地处理树的关系数据库。如果您想要更强大的功能,LDAP 可能适合您。

SQL 数据库不适合这种抽象拓扑。