关系数据库设计是否适合存储此复杂结构

时间:2018-06-27 18:21:55

标签: sql json database-design relational-database non-relational-database

TL; DR:

我想使用非关系设计将节点树存储在自引用表中,因为我们将不需要从关系上选择数据的子集。这样可以实现极其简单的递归存储和检索功能。

同事想使用关系设计来存储对象的每个特定字段-我想是因为他认为关系总是总是更好。 (他没有任何具体原因)这将需要更多表以及更复杂的存储和检索功能,而且我认为这不会以任何方式使我们受益。

这两种设计方法是否都有特定的好处或陷阱?

树通常如何存储在数据库中?自引用表?

数据库中是否存在任何已知的数据树样本,可能与我们要解决的任务相符?


在工作中,我们使用复杂的结构来描述对象,不幸的是,由于工作限制,我无法共享确切的结构,但是我将给出一个等效的结构示例并解释其功能。

该结构可以用json表示,但实际上符合更严格的语法限制。

结构中有四种实体:

  • 顶级节点
    • 此节点是json对象,它必须是顶级json对象
    • 此节点必须恰好包含4个属性(元信息1到4)
    • 此节点必须恰好包含1个“主”容器节点
  • 容器节点
    • 这些是包含其他容器和模式节点的json对象
    • 必须完全包含1个名为“ container_attribute”的属性
    • 可以包含任意数量的其他容器和样式
  • 模式节点
    • 这些是包含3个属性的json对象
    • 模式从技术上讲是一个容器
    • 可能不包含其他任何内容
  • 属性节点
    • 这些只是json字符串对象

顶级容器始终是一个json对象,其中包含4个属性和1个名为“ main_container”的容器

所有容器必须包含一个名为“ container_attribute”的属性。

所有模式必须完全包含三个属性

json中的结构示例如下:

{
    "top_level_node": {
        "meta_info_1": "meta_info_keyword1",
        "meta_info_2": "meta_info_keyword2",
        "meta_info_3": "meta_info_keyword3",
        "meta_info_4": "unique string of data", 

        "main_container": {
            "container_attribute": "container_attribute_keyword",

            "sub_container_1": {
                "container_attribute": "container_attribute_keyword",

                "pattern_1": {
                    "pattern_property_1": "pattern_property_1_keyword",
                    "pattern_property_2": "pattern_property_2_keyword",
                    "pattern_property_3": "unique string of data"
                },

                "pattern_2": {
                    "pattern_property_1": "pattern_property_1_keyword",
                    "pattern_property_2": "pattern_property_2_keyword",
                    "pattern_property_3": "unique string of data"
                }
            },

            "pattern_3": {
                "pattern_property_1": "pattern_property_1_keyword",
                "pattern_property_2": "pattern_property_2_keyword",
                "pattern_property_3": "unique string of data"
            }
        }
    }
}

我们想将此结构存储在内部办公数据库中,建议使用三个表,一个表将所有json对象存储在一个自引用表中,另一个表将所有json字符串存储在一个引用json的表中对象表,然后是第三个表,用于将顶级容器与对象名称相关联。

架构看起来像这样:

一个attibutes表将用来存储所有为js​​on字符串的内容,并引用父容器ID:

CREATE TABLE attributes (
    id                  int DEFAULT nextval('attributes_id_seq'::text),
    name                varchar(255),
    container_id        int,
    type                int,
    value_type          int,
    value               varchar(255)
);

容器表将用于将所有容器存储在自引用表中以创建“树”结构:

CREATE TABLE containers (
    id                  int DEFAULT nextval('containers_id_seq'::text),
    parent_container_id int 
);

然后是指向对象的顶级容器ID的单个对象名称列表:

CREATE TABLE object_names (
    id                  int DEFAULT nextval('object_names_id_seq'::text),
    name                varchar(255),
    container_id        int
);

上述结构的优点在于,它使真正简单的递归函数可以迭代树并存储属性和容器。

缺点是它根本不是关系的,因此不利于执行复杂的关系查询来检索信息集。

我说我们应该使用它的原因是因为我们绝对没有理由以关系方式选择这些对象的片段,每个对象上的数据仅在该对象的上下文中有用,并且我们没有任何情况除了重建对象外,出于任何原因我们都需要选择此数据。

但是我的同事说我们应该使用关系数据库设计来存储它,并且每个“关键字”属性都应该有自己的表(容器关键字表,3个模式关键字表,4个顶级关键字表) )。

结果是将这些对象存储在建议的关系设计中变得非常复杂,并且需要更多表。

请注意,查询速度/效率不是问题,因为此对象/数据库仅供内部使用,目的完全不对时间敏感。最终,我们要做的就是创建新的“对象”并存储它们,然后稍后查询数据库以重建所有对象。

如果关系数据库设计没有任何好处,那么是否有任何理由使用它来支持如此简单的存储/检索API?

我的建议架构是否存在重大问题?

1 个答案:

答案 0 :(得分:1)

“我们永远不需要X”是一个相当大胆的假设,事实证明,不必要的频率比您想像的要高。特别是对于树结构,最自然的要求是在短时间内“放大到一个节点”并将其视为一棵树。

编辑

如果不清楚为什么这么重要:关系方式往往会提供更大的灵活性,因为这种灵活性内置在数据结构中。一旦需求开始发展,非关系方法(通常意味着一切都在代码中解决了)趋向于导致新一轮的代码交换。