V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lonelinsky
V2EX  ›  程序员

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

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

    现在有表 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   ·   我们的愿景   ·   实用小工具   ·   3195 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:37 · PVG 08:37 · LAX 17:37 · JFK 20:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.