一表与多表中的一个关联的数据库设计问题求助

2016-05-05 15:27:21 +08:00
 lonelinsky

现在有表 A 可能与表 B , C , D , E , F...等中的一个关联, 其中 B,C,D,E,F 可能随着业务发展增加,那么在这样的情况下应该如何设计数据库比较合适呢? 目前的代码环境是数据库 Postgre + Django 。

我现在的想法有三个:

  1. 表 A 种增加两列,分别表征类型和 ID ,类型的内容为 B,C,D,E 等, ID 为对应 B,C,D,E 的内容的 ID ,但是感觉这样实现的话,最后的查询效率比较查,尤其是当我需要显示所有 A 以及 A 关联的 B , C,D 内容的时候。

  2. 根据 B , C , D 等建立多个中间表,两端分别指向 A 和 B , C , D ,这样的话基于中间表做联合查询就比较简单了(如果是 Django 的话, ORM 也可以直接用了),但是问题是这个导致 A 只能与 B , C , D 种的一个关联这样的约束不存在了,而且查询所有的话也比较麻烦。

  3. 直接扩展 A 表,根据 B , C, D 的数量增加列,分别指向 B , C , D ,这样的话查询所有的接口会变简单,但是每次增加表的时候,会导致 A 必须跟着改,感觉侵入性有点强。

大家有没有更好的方法呢?欢迎告知,谢谢。

3495 次点击
所在节点    程序员
11 条回复
mahone3297
2016-05-05 16:08:15 +08:00
2 没看懂
感觉还是要看可扩展性或者你的数据吧
1 的话,可扩展性强
3 的话,如果表 B , C 差的不多,可以考虑。差的多的话,我觉得还是选 1 吧
lonelinsky
2016-05-05 16:35:22 +08:00
@mahone3297 谢谢

我个人也相对倾向于 1

2 想说的就是根据 B , C , D ,新建 map_B, map_C, map_D 这样的表,表的内容是 A_id, B_Id(C_id, D_id)这样的东西,在查询的时候可以用这些 map 表查询,也可以根据 A 查询,不过我个人也不喜欢这种实现,总觉的太零散了…
Aksura
2016-05-05 22:12:41 +08:00
没看明白 2 ,为什么要建立多个中间表?只建一个中间表,存储表 A 与 表 B(C 、 D 、 E ...) 的关联不行吗?
lonelinsky
2016-05-05 22:21:59 +08:00
@Aksura 多张中间表的话关联关系是这样的:
A-B: [foreigin-key(A), foreign-key(B)],
A-C: [foreign-key(A), foreign-key(C)],
...
这样的表直接使用 Django 自带的 ORM 去查询的时候比较简单,如果只建立一个中间表的话,必须要引入类型,那么和 A 的方法其实是一样的。
Aksura
2016-05-05 22:55:06 +08:00
@lonelinsky 嗯,你说得对。引入类型的话,就不能利用好外键了。方案一和一个中间表都不合适了。方案三,如果表 A 数据量大访问的话,也不合适。如果表 B 、 C 、 D... 可能增长的数量不多,那么方案二是好些。
georgema1982
2016-05-06 00:26:48 +08:00
你能不能给出一个现实生活中的例子来说明 B,C,D,E,F 会不断增长的案例?如果类似的 model 会不断增长,多半是你设计有问题了
lonelinsky
2016-05-06 00:36:51 +08:00
@georgema1982 其实就算不考虑增加,我觉得在设计上也应该多加思考的,比如考虑设计商城的优惠券这样的问题吧,优惠券的使用范围分为 商家, 品类,商品,或者是所有可用,在这种情况下,优惠券可能和三个表关联,你觉得在这种情况下怎么设计数据库会比较合适呢? 我上面提到的动态增加,只是在想系统能不能设计扩展性更强一些…
domty
2016-05-06 10:50:12 +08:00
1 方案我以前试过类似的,其实就是 2,3 方案的折衷。
如果出现这样的需求:
显示 a 的内容,以及跟 A 所关联的其他表的内容(可能是 B,也可能是 C 等其他的表)
这个查询非常糟糕。不管是多结果集的 union 还是多表的 join 。


2 是最符合范式的做法,当然用起来会非常繁琐。
3 的副作用太大。

其实有没有考虑过,把你说的 B,C,D 等等多个表抽象成一个表(假设 Z 表)。不同的属性打包成 json 存起来,存前 json 序列化,取出 json 反序列化。
反正是和 A 表一一对应的关系,这个表的规模应该是 A 相等的。
lonelinsky
2016-05-06 13:11:59 +08:00
@domty 这个 json 方案我也考虑过,但是如果出现过滤条件在 json 序列化的部分会比较难处理… 其实用 2 让我觉得最不爽的就是感觉表很零散,没有很好的办法来处理,感觉很失控,没有一个地方可以查出来现在都有那些 map 表之类的数据(从数据的 meta 数据查我觉得也不是很好的方案)。

谢谢你的建议,我现在感觉如果最终的 BCD 表的数量不是很多的情况,可能用 1 还会是一个不错的方案? 你说的查询糟糕是指性能上还是说代码写法上比较糟糕?
georgema1982
2016-05-25 04:09:31 +08:00
@lonelinsky 如果是这种需求的话,那你确实是应该用第一种方案,但是不要自己发明轮子,因为 django 有 contenttype framework 来解决这种所谓的 generic foreign key 的问题。
lonelinsky
2016-05-25 09:57:30 +08:00
@georgema1982 果然我看文档不够仔细, contenttype framework 确实是个很好的解决方案,多谢,多谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/276533

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX