database - 存储分层数据的最佳方式(父 <- 子 <- 孙)
问题描述
我有一个需要使用的数据集,它代表大型机器的零件示意图。我需要为此数据集提出一个适当的数据库模式,并且在想出一些可以有效表示此数据的东西时遇到了麻烦。
顶级组件是最大的“结构”,当您向下遍历层次结构时,数据代表内部组件或构成内部组件的组件。例如,在顶层,可能有一个发动机作为级别 1 组件,然后级别 2 组件是进入发动机的活塞,级别 3 组件可能是进入活塞的垫圈。
此表示分布在 CSV 文件的几百行中。ID 有 3 列:
- a
master_id
,所有组件都有 - a
parent_id
,所有组件都具有,但它们的值因情况而异。- 如果有问题的组件是 1 级部件,
parent_id
则它是它自己的 master_id。 - 如果所讨论的组件是 2 级零件,
parent_id
则master_id
1 级组件的 。 - 如果所讨论的组件是 3 级零件,
parent_id
则master_id
2 级组件的。
- 如果有问题的组件是 1 级部件,
基本上,任何组件的父 id 都是其上一级组件的主 id。所以 lv1 parent 是 lv1 master(因为它是根), lv2 parent 是 lv1 master, lv3 是 lv2 master。此外,多个组件可以共享一个父 ID,这意味着多个 lv2 部件可以具有相同的父 ID。
- a
grandparent_id
,只有 3 级组件具有(但由于某种原因并非所有 lv3 组件(idk 我没有制作此数据集))。如果组件是 lv3 并且具有grandparent_id
,则祖父母 ID 是返回到 lv1 组件的主 ID 的直接链接。是的,很混乱对吧?
所以这里有一个例子。一个lv3组件的amaster_id
为700000137,aparent_id
为600000049,agrandparent_id
为500000006。如果我们查看master为600000049的组件,我们会看到这是一个父id为500000006的lv2组件,即一个 lv1 组件的主ID,也是这个 lv3 组件的祖父母。
我在这篇文章的开头说我需要为这个数据集提出一个数据库表示(它后来在项目中使用,但数据组织是第一步)。我很喜欢使用 PostgreSQL,所以我最初的想法是创建 3 个表,主表、父表和祖父表,根据我解析出来的键,我会将其插入到适当的数据库中,并将外键返回到如果有父键或祖父键,则为其他表。但是我意识到这可能会变得很麻烦,特别是因为可能有多个外键链接回一个主 ID,而且我觉得通过这种表示,一些数据可能会重复,我显然不希望发生这种情况。
我的第二个想法是使用类似于 python 字典的东西,我基本上构建了一个树状结构,其中 lv1 组件位于顶层,lv2 组件位于第二层等。然后我可以将字典转换为 JSON,因为Python 就是这样很好,并将该 json blob 存储在数据库中。但是,这个 JSON blob 可能会变得非常大,尽管我想这只是随着数据集的增长我不得不忍受的东西。我得到的这部分示意图仅适用于一台机器,所以基本上我的数据库中的每个条目都会像
id | name | json
----------------------
1 | machine_a | JSON_BLOB_MACHINE_A
----------------------
2 | machine_b | JSON_BLOB_MACHINE_B
etc...
我的第二种方法似乎比尝试创建代表每个部分级别和外键返回父母的单独表更好吗?如果有更好的方法来使用 Postgres 做到这一点,我会很感激你解释它。否则,我可能会选择后一条路线。谢谢!
解决方案
如果您不需要在其他机器中加入零件,那么我认为jsonb
零件列可能是最好的。您仍然可以使用GIN索引对 jsonb 进行索引,并从查询中获得非常好的性能。
只要零件不在许多机器之间共享,这会使在所有机器上更新零件属性变得很棘手,那么您可能就可以了。
由于大部分数据是自包含的,因此这应该可以轻松查询机器。
推荐阅读
- spring-boot - 基于 OAuth2 的登录到 localhost:8080 使用 Google 导致重定向到相同的登录页面
- javascript - 根据鼠标指针放大对象
- amazon-web-services - 使用 Cloudflare 在 AWS Lambda 上部署 SSR Nuxt.js?
- javascript - 正则表达式问题(长字符串)
- r - 在R中将大数据帧写入csv?
- pandas - 如何使用熊猫查找列的最大值并根据条件按顺序排列它们?
- wpf - MVVM 索引绑定
- android - NavController.handleDeepLink() 不工作
- bash - Obexctl:在终端和脚本中提供不同的结果
- c# - EPPlus 显示系统参数异常