【问题标题】:How to represent a tree like structure in a db如何在数据库中表示树状结构
【发布时间】:2023-03-14 01:45:02
【问题描述】:

我正在启动一个项目,并且正处于设计阶段:也就是说,我还没有决定要使用哪个数据库框架。我将编写创建类似“森林”结构的代码。也就是说,许多树,其中每棵树都是一个标准:节点和边。代码创建这些树后,我想将它们保存在数据库中。 (然后最终将它们拉出来)

在数据库中表示数据的简单方法是使用两个表的关系数据库:节点和边。也就是说,nodes 表会有一个node id,node 数据等。edges 表会是node id 到node id 的映射。

有没有更好的方法?或者鉴于我给出的(有限)假设这是最好的方法?如果我们添加一个树相对较小的假设 - 将整个树保存为数据库中的 blob 会更好吗?在这种情况下我应该使用哪种类型的数据库?请评论速度/可扩展性。

谢谢

【问题讨论】:

  • 我也一直在考虑这个问题,我想存储当前节点的父节点数组。我尚未对其进行测试,但想知道这是否是最佳解决方案。
  • 听起来您并没有将数据库用作数据库。通常,树用于完成一些其他抽象目标,例如创建集合或地图/字典。我认为您需要弄清楚您正在使用的抽象数据结构并询问如何将 that 映射到数据库。你在你的森林里储存了什么?
  • 您需要支持什么样的查询?您可以使用邻接列表(您当前的想法)、嵌套集,甚至(在适当的数据库支持下)节点 ID 数组来表示从根开始的路径。您选择哪种表示形式取决于您需要对数据执行的操作。
  • @Kim,为什么是数组?如果图是一棵树,每个节点最多有一个父节点。
  • @svick,因此更容易根据祖先过滤子树。

标签: database data-structures tree hierarchical-data


【解决方案1】:

在我对 StackOverflow 问题的回答中,我展示了一个类似于您的节点和边表的解决方案:What is the most efficient/elegant way to parse a flat table into a tree? 我将此解决方案称为“闭包表”。

我做了一个关于在 SQL 中存储和使用树的不同方法的演示,Models for Hierarchical Data with SQL and PHP。我演示了使用正确的索引(取决于您需要运行的查询),Closure Table 设计可以具有非常好的性能,即使是在大量边(在我的演示中大约有 500K 边)的情况下。

我还在我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming 中介绍了这个设计。

【讨论】:

  • 假设我决定在内存中保留一个表示树的数据结构(因为我有许多树,其键指向它们。即键->树)。例如,我可以从我的树中创建一个 JSON 并将其保存为字符串。在这种情况下,我最好使用非关系数据库吗?和(因为我从未使用过非关系数据库)你能推荐哪个非关系数据库?
  • 您可以确定将 JSON 字符串填充到非关系数据库中,但在将其从数据库中拉出之前,您将无法对其进行任何操作。如果您希望获取整个树,将其反序列化为应用程序对象,并编写递归函数来遍历树,那很好。如果您想要一种查询语言,您可以使用它来获取子树或通过树的路径,请使用关系建模。
  • @Bill Karwin 请参阅与您的幻灯片相关的stackoverflow.com/questions/13302187/sql-query-optimize。
  • @user151496,如果您从节点 C 开始查询子树,您将获得 C 以下所有节点的所有集合。您是对的,仅凭这一点不足以显示层次结构。但是您可以将这些后代节点连接到连接到其祖先或后代的路径段。我在演示文稿中展示了我链接到的示例。
  • @Gus,如果您有 XML 文档,请将其存储在 TEXT 列中。如果您希望能够查询单个元素,您可以使用内置 XML 函数,例如 MySQL:dev.mysql.com/doc/refman/5.7/en/xml-functions.html。但这不会被索引。如果您想要高性能查询,请将 XML 分解并将元素存储在离散的行中。
【解决方案2】:

一定要对被树化的实体使用某种低级编码,以防止循环。实体可能是部件、主题、文件夹等。

使用实体文件和实体外部参照文件,您可以遍历两个文件之间的两种关系之一,即父关系和子关系。

级别是在树中找到的实体的级别。实体的低级代码是在任何地方的任何树中都可以找到实体的最低级别。检查以确保您要创建子实体的低级代码小于或等于以防止循环。将实体添加为子实体后,它将至少降低一级。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    • 2023-04-02
    • 2020-01-23
    • 1970-01-01
    相关资源
    最近更新 更多