V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
Macv1994
V2EX  ›  程序员

大家在建表的时候都使用外键吗?

  •  2
     
  •   Macv1994 ·
    weijiang1994 · 2020-12-22 10:53:45 +08:00 · 8664 次点击
    这是一个创建于 1465 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在上一家公司不准使用外键,新入职一家公司,发现数据表中使用了很多外键,不知道大家日常是怎么操作的?

    84 条回复    2020-12-23 16:23:19 +08:00
    sxfscool
        1
    sxfscool  
       2020-12-22 10:58:42 +08:00
    很久没用过外键了
    dddz97
        2
    dddz97  
       2020-12-22 11:00:10 +08:00
    基本没用过
    xcai007
        3
    xcai007  
       2020-12-22 11:03:54 +08:00
    可以使用外键
    liuzhaowei55
        4
    liuzhaowei55  
       2020-12-22 11:04:13 +08:00 via iPhone
    不用外键,甚至已经比较少使用主键关联了,使用业务唯一对象关联比较多
    Macv1994
        5
    Macv1994  
    OP
       2020-12-22 11:05:32 +08:00 via Android
    @liuzhaowei55 感觉外键有时候还挺方便的😹😹😹
    yisheyuanzhang
        6
    yisheyuanzhang  
       2020-12-22 11:07:51 +08:00
    没用过外键。。。
    liuzhaowei55
        7
    liuzhaowei55  
       2020-12-22 11:08:00 +08:00 via iPhone
    @Macv1994 使用主键外键后期排查问题不太方便,要先去原表查出主键再去查外键数据,要不就是一个大 join,
    SjwNo1
        8
    SjwNo1  
       2020-12-22 11:09:56 +08:00
    可以用但不用
    WhoMercy
        9
    WhoMercy  
       2020-12-22 11:12:58 +08:00
    V2 因为外键、范式的问题讨论 /争吵过好几次了...

    我的意见是,自己不确定 能不能用、需不要需要用 的时候,就不用
    zjsxwc
        10
    zjsxwc  
       2020-12-22 11:14:04 +08:00   ❤️ 4
    外键的目的是为了数据的完整性和一致性,

    对于多表之间需要强数据一致性和完整性要求业务,且数据库会被不同语言或不同项目连接时, 我会用外键,因为不能保证别人或别的项目一定会知道,我这个项目要求哪些表之间数据是必须要有的。

    但绝大部分一般业务我不会加数据库外键,因为大部分情况下,我们都在同一个项目下,使用同一套 编程语言别写的业务代码,来处理业务,而在业务层面,使用编程语言来约束更具有灵活性。
    Macv1994
        11
    Macv1994  
    OP
       2020-12-22 11:14:20 +08:00 via Android
    @WhoMercy 我自己写的博客就用了,感觉很方便。但是不知项目体量大了,体验是否会变差?
    Macv1994
        12
    Macv1994  
    OP
       2020-12-22 11:17:18 +08:00 via Android
    @zjsxwc 嗯嗯,是这样。但是如果到业务层面去处理,是不是会增加代码量?
    SkyLine7
        13
    SkyLine7  
       2020-12-22 11:19:11 +08:00
    用外键级联很麻烦的,现在都拿关联字段当做逻辑外键
    Tink
        14
    Tink  
       2020-12-22 11:19:48 +08:00
    少用
    acmore
        15
    acmore  
       2020-12-22 11:20:59 +08:00
    现在的业务并不喜欢让数据库做太多掌控之外的事情,外键算是最不讨喜的一个。
    以及外键在配合某些 ORM 框架使用时可能会有暗坑,你无法预设 "outer.inner" 这种写法一定会缓存结果,背后可能会有一堆查询在,还是要提前查询好 inner 再给 outer 用,那还不如不要外键。
    xuxuzhaozhao
        16
    xuxuzhaozhao  
       2020-12-22 11:22:09 +08:00
    @WhoMercy 同意!
    zjsxwc
        17
    zjsxwc  
       2020-12-22 11:32:12 +08:00
    @Macv1994 #12

    这倒没有,不用数据库外键,
    不代表你自己编程语言业务里面不用外键,这种外键,就是“软外键”
    securityCoding
        18
    securityCoding  
       2020-12-22 11:34:24 +08:00
    基本没用过了 , 一般通过中间表解决
    cco
        19
    cco  
       2020-12-22 11:45:08 +08:00
    可以用外键,但是很久不用了。你觉得需要约束就用一下,没必要就不需要。
    DarkCat123
        20
    DarkCat123  
       2020-12-22 11:49:52 +08:00
    测试环境用外键,生产不用。
    hantsy
        21
    hantsy  
       2020-12-22 11:50:35 +08:00   ❤️ 2
    一直使用 JPA,只要有关联的情况, 一直使用外键。
    1 。 保持数据一致性太重要
    2 。 另外 JPA 的并发管理,Version 更新都是有关联有关。

    (当然不同 Domain 之间数据库也断开直接关联,简单的一个外键引用,与代码一致)。

    不用外键,编程上灵性,为了数据一致性,额外要做很多工作,数据库管理也麻烦。当然可以增加无脑打酱油的时间。
    abyan1314
        22
    abyan1314  
       2020-12-22 12:01:42 +08:00 via Android   ❤️ 5
    尽量不要使用外键
    - 有额外开销
    - 逐行操作
    - 可“到达”其他表,意味着锁
    - 高并发时容易产生死锁
    sampeng
        23
    sampeng  
       2020-12-22 12:17:10 +08:00
    用外键就是程序员偷懒,无一例外
    limuyan44
        24
    limuyan44  
       2020-12-22 12:20:48 +08:00 via Android
    很多年不用了,没有什么足够的价值去使用。
    manami
        25
    manami  
       2020-12-22 12:22:04 +08:00 via Android
    外键恐惧症
    tokyo2020
        26
    tokyo2020  
       2020-12-22 12:23:53 +08:00
    @abyan1314 我觉得这是使用外键的好处啊,mysql 官方文档都说了 使用外键可以充分利用索引,提高查询速度。
    love
        27
    love  
       2020-12-22 12:52:38 +08:00
    @tokyo2020 外键和查询速度有什么关系?的确建外键会自动给你建个索引,但你不会自己建吗
    Macv1994
        28
    Macv1994  
    OP
       2020-12-22 13:27:10 +08:00
    @sampeng 你这么说也有道理,用外键确实减少了一部分工作
    bnm965321
        29
    bnm965321  
       2020-12-22 13:27:31 +08:00
    看来都是 Java 大佬。

    使用 Python, Ruby 的肯定都会用外键
    nxy006
        30
    nxy006  
       2020-12-22 13:31:16 +08:00
    毕业以后就没用过外键了

    不用外键,意味着不使用任何跨表查询。
    inorilzy
        31
    inorilzy  
       2020-12-22 13:31:25 +08:00 via Android
    @bnm965321 python 也不用,这和语言没有关系吧。
    nxy006
        32
    nxy006  
       2020-12-22 13:35:02 +08:00
    @bnm965321
    Rails 就是不使用外键的,用自定义校验器功能丰富,代替数据库校验。当然 Rails 的跨表查询功能比较强,会有一些跨表查询,但外键还是不用。
    duhui
        33
    duhui  
       2020-12-22 13:36:29 +08:00
    @bnm965321 为啥 Ruby 会用, 主流的 Ruby on Rails 就不用啊
    duhui
        34
    duhui  
       2020-12-22 13:40:36 +08:00
    @nxy006 没外键也能跨表啊
    mandex
        35
    mandex  
       2020-12-22 13:41:37 +08:00
    不用
    itIsUnbelievable
        36
    itIsUnbelievable  
       2020-12-22 13:41:50 +08:00
    萌新问个问题,比如说一个人的爱好有很多种,如果不用外键的话要怎么存到一张表呢?
    tingyunsay
        37
    tingyunsay  
       2020-12-22 13:48:13 +08:00
    外键用过,常需要改动的数据绝对不用外键,不灵活
    hodur
        38
    hodur  
       2020-12-22 13:52:16 +08:00
    @itIsUnbelievable 不用外键约束,但是还是存在表 join 的
    xh520630
        39
    xh520630  
       2020-12-22 13:55:38 +08:00
    @itIsUnbelievable
    不用外键只是少了个约束.
    你内容该怎么存还是怎么存.
    id, 用户 id, 爱好 id/爱好名称
    CismonX
        40
    CismonX  
       2020-12-22 14:14:22 +08:00   ❤️ 2
    我司开发规范里面是禁止外键的,建表的时候就不允许

    但是实际开发实践中,“逻辑外键”还是广泛存在的,也就是用一个表中的字段值作为另外一个表的查询条件。含有 join 的语句也是允许的(但仅限 select 。update 和 delete 语句中不允许 join )
    Macv1994
        41
    Macv1994  
    OP
       2020-12-22 14:24:59 +08:00
    @CismonX 我上一家公司也差不多是这样....
    ArJun
        42
    ArJun  
       2020-12-22 14:27:50 +08:00
    没事的,多用、到时候换人了换不动变相加薪···
    wangbudong
        43
    wangbudong  
       2020-12-22 14:31:06 +08:00
    以前用得多,现在基本少用
    wangbudong
        44
    wangbudong  
       2020-12-22 14:31:33 +08:00
    还是因为外键联动起来数据处理麻烦
    steptodream
        45
    steptodream  
       2020-12-22 14:35:35 +08:00
    我用 django 都是小项目 外键方便的不行
    Macv1994
        46
    Macv1994  
    OP
       2020-12-22 14:36:10 +08:00
    @itIsUnbelievable 外键只是约束数据,不用外键也可以存
    Macv1994
        47
    Macv1994  
    OP
       2020-12-22 14:36:59 +08:00
    @steptodream 确实我自己写的几个 flask 小项目也是用的外键 真的减少很多工作量 不知道体量大的项目 应该怎么实践
    lbunderway
        48
    lbunderway  
       2020-12-22 14:39:37 +08:00
    用外键,不用约束
    ren2881971
        49
    ren2881971  
       2020-12-22 14:49:47 +08:00
    逻辑外键。
    qilishasha
        50
    qilishasha  
       2020-12-22 14:55:58 +08:00 via iPhone
    如果有一位麻烦的甲方或想法多的项目设计经理,可以尝试的用一下外键,你将会知道头发的珍贵
    leeton
        51
    leeton  
       2020-12-22 14:58:24 +08:00
    不用外键 感觉很反人类
    Lemeng
        52
    Lemeng  
       2020-12-22 15:02:15 +08:00
    不用,但可以,个人习惯
    mamasan
        53
    mamasan  
       2020-12-22 15:11:45 +08:00
    我想问下, 不使用外键, 最简单的用户, 角色, 权限这种需要 5 张表的怎么查询啊?
    Macv1994
        54
    Macv1994  
    OP
       2020-12-22 15:24:28 +08:00
    @leeton 为什么觉得会反人类
    qaz168000
        55
    qaz168000  
       2020-12-22 15:41:54 +08:00
    确实很多年没有用过外键了,一般都是逻辑外键
    dorothyREN
        56
    dorothyREN  
       2020-12-22 15:44:03 +08:00
    我寻思着,有外键会写 sql,没外键就不会写 sql 了?
    wupher
        57
    wupher  
       2020-12-22 15:44:21 +08:00   ❤️ 5
    不推荐,最好不用。

    使用的好处是在数据库层来维护表间数据关联。但是,除非你是传统的 CS 程序,业务逻辑仍然以存储过程的形式编写,存在。现在一般是使用程序来建模,实现业务,相关逻辑更应该在代码,而非数据库层来进行维护。

    使用数据层的坏处有
    * 数据维护困难,某些数据的存在与删除由于外键、约束会导致很难维护
    * 数据库层较难切换,同上
    * 数据库升级麻烦,同上

    现代设计更推荐将数据库仅视为存储与查询的简单组件,尽量较低业务依赖。
    0bit
        58
    0bit  
       2020-12-22 15:49:14 +08:00
    想一想有没有过度优化,想一想自己在做的项目的并发要求有多大,开发周期有多久,权衡取舍一下就行了,没必要非此即彼。
    skypyb
        59
    skypyb  
       2020-12-22 15:53:25 +08:00
    在公司不用, 我自己项目会用。
    主要是为了方便快速的开发, 维护丢给数据库后可以少耗些精力。 本身个人项目一般也达不到外键会影响到的量级, 开发效率至上
    tokyo2020
        60
    tokyo2020  
       2020-12-22 15:56:05 +08:00
    @love 因为为啥还要再建这个副本数据的索引呢,我还要确保这个值在这 2 张表中是不是都存在,可能还要维护数据。 见《 SQL 反模式》 这本书 5.2 章节
    stdout
        61
    stdout  
       2020-12-22 15:57:19 +08:00
    连 join 都很少用了。关联越少越好
    Macv1994
        62
    Macv1994  
    OP
       2020-12-22 16:11:20 +08:00
    @skypyb 我是开发了几个自己的小项目之后有这样的疑问,自己的小项目用外键感觉可以省去很多工作量。现在的公司也用外键,但是业务都是公司内容的业务,可能是这个原因导致的吧。上一家公司都是外部业务,可能就是禁止使用外键的原因吧。
    Macv1994
        63
    Macv1994  
    OP
       2020-12-22 16:12:20 +08:00
    @wupher 嗯嗯 确实使用了外键数据比较难维护 亲身经历的感受
    charlie21
        64
    charlie21  
       2020-12-22 16:20:33 +08:00
    有 ORM 还要什么外键
    yujieyu7
        65
    yujieyu7  
       2020-12-22 16:33:09 +08:00
    从来不用,mysql 只负责存储就好了,逻辑还是交给应用程序吧
    ming7435
        66
    ming7435  
       2020-12-22 17:09:44 +08:00
    Never
    duhui
        67
    duhui  
       2020-12-22 17:14:13 +08:00
    @charlie21 PHP 的一个 ORM Doctrine 就在关联的时候加外键啊, 而且还不能禁用
    totoro52
        68
    totoro52  
       2020-12-22 18:53:20 +08:00
    大学生才用外键
    msg7086
        69
    msg7086  
       2020-12-22 19:01:53 +08:00 via Android
    @tokyo2020 #59 外键和非外键的区别仅仅在于数据完整性约束,和索引没有直接关系。
    huobazi
        70
    huobazi  
       2020-12-22 19:04:52 +08:00
    《学生选课系统》 必须用,不用就挂科了
    liprais
        71
    liprais  
       2020-12-22 19:05:08 +08:00 via iPhone
    说不能用的可以想象你们的数据有多脏
    rexyan
        72
    rexyan  
       2020-12-22 19:32:07 +08:00
    像 DRF 这种自带的 ORM 的咋整,不用感觉不方便
    Macv1994
        73
    Macv1994  
    OP
       2020-12-22 19:51:13 +08:00
    @rexyan DRF 没用过不太清楚 Python 的 sqlachemy 不是自带外键的呀
    Macv1994
        74
    Macv1994  
    OP
       2020-12-22 19:51:55 +08:00
    @huobazi 这种课程的没问题 体量不大 用外键反而更加方便 减少工作量
    hejw19970413
        75
    hejw19970413  
       2020-12-22 21:02:14 +08:00
    不会用外键
    hejw19970413
        76
    hejw19970413  
       2020-12-22 21:03:44 +08:00
    如果你的领导很厉害,说这里必须用外键或者说自己感觉这里能用而且用后的结果比不用外键好的太多,那就可以用。
    justNoBody
        77
    justNoBody  
       2020-12-22 21:36:55 +08:00
    @abyan1314 #22 数据库死锁一定要小心
    kkbblzq
        78
    kkbblzq  
       2020-12-22 22:40:12 +08:00
    1. 外键会导致多表关联锁,这对并发场景是挺严重的问题,特别是很多时候性能瓶颈可能就落数据库上,外键无疑雪上加霜。
    2. 依赖外键来做完整性虽然省事,但是同时你也耦合了数据库的逻辑,数据库层切换就很麻烦,要做数据层改造也很麻烦,比如你哪天想在上面加一层缓存。
    Macv1994
        79
    Macv1994  
    OP
       2020-12-22 22:46:36 +08:00
    @kkbblzq 嗯嗯,所以我觉得还是得看场景,不能一概而论。
    leeton
        80
    leeton  
       2020-12-23 09:50:55 +08:00
    @Macv1994 感觉删数据的时候很不方便,必须得先删有外键那个表,这就很烦。很不自由
    qiyuey
        81
    qiyuey  
       2020-12-23 10:08:53 +08:00
    我们是禁止使用外键
    xiangbohua
        82
    xiangbohua  
       2020-12-23 13:56:08 +08:00
    现在大多数 application 都是 orm 访问数据库,但是 orm 对于外键的支持一直都不好。
    一般都不用
    joesonw
        83
    joesonw  
       2020-12-23 14:42:33 +08:00
    mysql 就别用了. 如果上了 oracle 什么的商业数据库, 外键倒是搞不死.
    laravel
        84
    laravel  
       2020-12-23 16:23:19 +08:00
    用了能有多大用?没多大用就别用了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2997 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 14:36 · PVG 22:36 · LAX 06:36 · JFK 09:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.