一表与多表中的一个关联的数据库设计问题求助 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
lonelinsky
V2EX    程序员

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

  • &nbs;
  •   lonelinsky 2016-05-05 15:27:21 +08:00 3877 次点击
    这是一个创建于 3513 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在有表 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 必须跟着改,感觉侵入性有点强。

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

    11 条回复    2016-05-25 09:57:30 +08:00
    mahone3297
        1
    mahone3297  
       2016-05-05 16:08:15 +08:00
    2 没看懂
    感觉还是要看可扩展性或者你的数据吧
    1 的话,可扩展性强
    3 的话,如果表 B , C 差的不多,可以考虑。差的多的话,我觉得还是选 1 吧
    lonelinsky
        2
    lonelinsky  
    OP
       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
        3
    Aksura  
       2016-05-05 22:12:41 +08:00
    没看明白 2 ,为什么要建立多个中间表?只建一个中间表,存储表 A 与 表 B(C 、 D 、 E ...) 的关联不行吗?
    lonelinsky
        4
    lonelinsky  
    OP
       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
        5
    Aksura  
       2016-05-05 22:55:06 +08:00
    @lonelinsky 嗯,你说得对。引入类型的话,就不能利用好外键了。方案一和一个中间表都不合适了。方案三,如果表 A 数据量大访问的话,也不合适。如果表 B 、 C 、 D... 可能增长的数量不多,那么方案二是好些。
    georgema1982
        6
    georgema1982  
       2016-05-06 00:26:48 +08:00
    你能不能给出一个现实生活中的例子来说明 B,C,D,E,F 会不断增长的案例?如果类似的 model 会不断增长,多半是你设计有问题了
    lonelinsky
        7
    lonelinsky  
    OP
       2016-05-06 00:36:51 +08:00
    @georgema1982 其实就算不考虑增加,我觉得在设计上也应该多加思考的,比如考虑设计商城的优惠券这样的问题吧,优惠券的使用范围分为 商家, 品类,商品,或者是所有可用,在这种情况下,优惠券可能和三个表关联,你觉得在这种情况下怎么设计数据库会比较合适呢? 我上面提到的动态增加,只是在想系统能不能设计扩展性更强一些…
    domty
        8
    domty  
       2016-05-06 10:50:12 +08:00   1
    1 方案我以前试过类似的,其实就是 2,3 方案的折衷。
    如果出现这样的需求:
    显示 a 的内容,以及跟 A 所关联的其他表的内容(可能是 B,也可能是 C 等其他的表)
    这个查询非常糟糕。不管是多结果集的 union 还是多表的 join 。


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

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

    谢谢你的建议,我现在感觉如果最终的 BCD 表的数量不是很多的情况,可能用 1 还会是一个不错的方案? 你说的查询糟糕是指性能上还是说代码写法上比较糟糕?
    georgema1982
        10
    georgema1982  
       2016-05-25 04:09:31 +08:00   1
    @lonelinsky 如果是这种需求的话,那你确实是应该用第一种方案,但是不要自己发明轮子,因为 django 有 contenttype framework 来解决这种所谓的 generic foreign key 的问题。
    lonelinsky
        11
    lonelinsky  
    OP
       2016-05-25 09:57:30 +08:00
    @georgema1982 果然我看文档不够仔细, contenttype framework 确实是个很好的解决方案,多谢,多谢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4996 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 05:44 PVG 13:44 LAX 21:44 JFK 00:44
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86