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

[求助] 请教大家一个数据库设计的问题

  •  
  •   hustlzp ·
    hustlzp · 2014-04-03 08:49:58 +08:00 · 4358 次点击
    这是一个创建于 3887 天前的主题,其中的信息可能已经有所发展或是发生改变。
    网站的用户分2个群体,一边是teacher,另一边是student。

    teacher和student有很多字段是相同的,比如:name, sex, email, password, avatar, check_message_time, create_time。

    然后各自也有专属字段:

    * teacher:毕业大学、授课方式、类型(在校、在职)
    * student:性格、对老师的要求

    teacher和student的登陆、注册、找回密码等入口页面是一样的。然后teacher和student之间可以相互私信。

    有2种设计方案:

    * 方案A:单独的teacher表 + student表
    * 方案B:user表保存共有信息,额外的teacher表保存老师专有信息,额外的student表保存学生专有信息。user和teacher是一对一关系,user和student也是一对一关系。

    个人感觉方案A有点累赘,而方案B的话又带来了很多join操作。

    大家的看法是?或者有更好的设计方案,非常感谢!
    第 1 条附言  ·  2014-04-03 13:37:51 +08:00
    SQLAlchemy的declarative可以蛮好地解决这种问题,感谢各位!

    http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/declarative.html#inheritance-configuration
    22 条回复    1970-01-01 08:00:00 +08:00
    jones
        1
    jones  
       2014-04-03 09:00:07 +08:00 via Android   ❤️ 1
    以ORM的思维来说肯定是第二种,join一般不用担心,现代的ORM都带有延迟加载和缓存的功能,查询一个user对象其实也就一条普通的select,对象中只持有老师或学生的关联id,调用user的get老师方法的时候,ORM会自动去加载老师的数据,首先查找缓存,没有找到在另外发送一条SELECT,然后把返回的老师数据放入缓存中,当然这只是理想情况下,
    hustlzp
        2
    hustlzp  
    OP
       2014-04-03 09:11:19 +08:00
    @jones 感谢!第二种确实合适些~
    min
        3
    min  
       2014-04-03 09:12:20 +08:00   ❤️ 1
    怕join就把所有字段堆在user里面
    yyai3
        4
    yyai3  
       2014-04-03 09:14:30 +08:00   ❤️ 1
    活到老学到老,用户有没有可能即是学生也是老师?角色设计?
    hustlzp
        5
    hustlzp  
    OP
       2014-04-03 09:33:08 +08:00
    @yyai3 这种情况极其少,所以暂不考虑,强制某用户只有一个role。如果需要新的role,需重新注册。
    hustlzp
        6
    hustlzp  
    OP
       2014-04-03 09:34:09 +08:00
    @min 恩,考虑过,只不过差异的部分太大,会造成太多冗余字段,所以权衡后,还是join吧...
    min
        7
    min  
       2014-04-03 09:38:03 +08:00   ❤️ 1
    @hustlzp
    这个做法是一些orm里面处理继承结构的推荐做法,速度相对快
    冗余不冗余的,如果你用的orm能管好数据库的结构,也不是个问题
    lenmore
        8
    lenmore  
       2014-04-03 10:00:24 +08:00   ❤️ 1
    方案B吧
    需要join的地方可能就是一些列表而已,
    如果真的很在意join的性能,可以建一个索引视图,毕竟更新不会很频繁吧。
    helone
        9
    helone  
       2014-04-03 10:03:49 +08:00   ❤️ 1
    方案B吧,方案A坑很大。。。
    hustlzp
        10
    hustlzp  
    OP
       2014-04-03 10:08:33 +08:00
    @min 有道理,得去好好看看SQLAlchemy中的继承处理方法。
    hustlzp
        11
    hustlzp  
    OP
       2014-04-03 10:09:04 +08:00
    @min
    @lenmore 恩,想了下,如果A的话坑确实不少...
    merlin852
        12
    merlin852  
       2014-04-03 10:32:24 +08:00   ❤️ 1
    我觉得可以user一张表,再建一个user_prop,保存其他资料,user和user_prop一对多关系
    user_prop 可以类似如下:
    id,user_id, type ,value
    1, 10001, 10, xxxx
    2, 10001, 20, yyyy

    10代表毕业大学,20代表性格,30代表。。。。可以自己定义
    这样后续添加其他资料时不用更改表结构,相对好扩展点,检索起来应该也方便,可能sql写起来麻烦点
    hustlzp
        13
    hustlzp  
    OP
       2014-04-03 10:53:20 +08:00
    @merlin852 懂你意思了,这样灵活度很高,扩展很强啊~
    mahone3297
        14
    mahone3297  
       2014-04-03 11:36:41 +08:00   ❤️ 1
    看来大家都支持方案B啊。。。要么我也方案B吧。。。
    不过确实会有纠结,理解lz。。。
    yueyoum
        15
    yueyoum  
       2014-04-03 11:48:49 +08:00   ❤️ 1
    这有什么好纠结的

    class User(Model):
    id = ...
    name = ...
    passwd = ...

    ** other properties


    class Teacher(User):
    ....

    class Student(User):
    ....


    注册 登录 找密码 只用关心user表即可
    NetCobra
        16
    NetCobra  
       2014-04-03 12:21:00 +08:00   ❤️ 1
    让我选的话我用方案B,再加两个View,Join就留给View去做。
    NetCobra
        17
    NetCobra  
       2014-04-03 12:22:21 +08:00
    另外User和Teacher,User和Student不应该是一对一关系吧?一个User不应该同时是Teacher和Student。
    sheaven
        18
    sheaven  
       2014-04-03 13:14:24 +08:00   ❤️ 1
    这时候菲关系型数据库就笑了,可行的话考虑下mongodb
    hustlzp
        19
    hustlzp  
    OP
       2014-04-03 13:34:04 +08:00
    @yueyoum 感谢!万能的V2EX!
    hustlzp
        20
    hustlzp  
    OP
       2014-04-03 13:34:34 +08:00
    @sheaven 恩,非结构化确实方便!
    hustlzp
        21
    hustlzp  
    OP
       2014-04-03 13:35:28 +08:00
    @NetCobra 可能描述不太准确,User 和 Teacher+Student 应该是一一对应的。
    wwek
        22
    wwek  
       2014-04-03 13:43:28 +08:00   ❤️ 1
    每次看v友都说的很好
    我也在啰嗦下
    b方案. 共有信息放一张表.独有信息单独放.

    这个级别的join操作没关系.如果实在是规模比较大,以后做个中间件丢内存跑吧.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1106 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 18:44 · PVG 02:44 · LAX 10:44 · JFK 13:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.