一尘不染

在SQL中管理层次结构:MPTT /嵌套集,邻接列表,存储路径

sql

一段时间以来,我一直在努力如何最好地处理SQL中的层次结构。由于邻接表的限制以及MPTT
/嵌套集的复杂性而感到沮丧,我开始考虑将密钥路径简单地存储为简单的node_key/node_key/...字符串。我决定汇总以下三种技术的优缺点:

创建/删除/移动节点所需的呼叫数:

  • 邻接= 1
  • MPTT = 3
  • 路径= 1(用包含该路径的所有节点上的新节点路径替换旧节点路径)

获取树所需的调用次数:

  • 邻接度= [子级别数]
  • MPTT = 1
  • 路径= 1

获取节点/祖先路径所需的呼叫数:

  • 邻接度= [超级数]
  • MPTT = 1
  • 路径= 0

获取子节点数所需的调用数:

  • 邻接度= [子级别数]
  • MPTT = 0(可以从左/右值计算得出)
  • 路径= 1

获取节点深度所需的呼叫数:

  • 邻接度= [超级数]
  • MPTT = 1
  • 路径= 0

所需的数据库字段:

  • 邻接度= 1(父级)
  • MPTT = 3(父级,右,左)
  • 路径= 1(路径)

结论

在每个用例中,除了一个之外,存储路径技术使用的调用数量与其他技术相同或更少。通过这种分析,存储路径无疑是赢家。更不用说,它易于实施,易于阅读等。

因此,问题是,难道不应该将存储路径视为比MPTT更强大的技术吗?为什么存储路径不是更常用的技术,为什么在给定实例中不通过MPTT使用存储路径?

另外,如果您认为此分析不完整,请告诉我。

更新:

MPTT可以开箱即用地执行以下至少两项操作:存储路径解决方案无法做到:

  1. 允许计算每个节点的子节点数,而无需任何其他查询(如上所述)。
  2. 在给定级别的节点上施加顺序。其他解决方案是无序的。

阅读 155

收藏
2021-03-17

共1个答案

一尘不染

您可能还会考虑我在回答“将平面表解析成树的最有效/最优雅的方法是什么?”中描述的“闭合表”设计

创建/删除/移动节点所需的调用:

  • 闭包= 1

获取树所需的调用:

  • 闭包= 1

获取到节点/祖先路径所需的调用:

  • 闭包= 1

获取子节点数所需的调用:

  • 闭包= 1

获取节点深度所需的调用:

  • 闭包= 1

所需的数据库字段:

  • 邻接=每行多1个字段
  • 路径=多1个字段/行
  • MPTT =每行2或3个以上字段
  • 关闭=额外表中的2或3个字段。该表在 最坏的情况下 具有O(n ^ 2)行,但比大多数实际情况要少得多。

还有其他一些注意事项:

支持无限深度:

  • 邻接=是
  • MPTT =是
  • 路径=否
  • 关闭=是

支持参照完整性:

  • 邻接=是
  • MPTT =否
  • 路径=否
  • 关闭=是

我还将在演示文稿“使用SQL和PHP的层次结构数据模型”以及《SQL反模式:避免数据库编程的陷阱》一书中介绍闭包表。

2021-03-17