V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
cl903254852
V2EX  ›  MySQL

MySQL 不用外键的话,如何让表起来关联呢?

  •  1
     
  •   cl903254852 · 2019-09-16 10:52:48 +08:00 · 16153 次点击
    这是一个创建于 1677 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Mysql刚入门,看到有人说表关联不要用外键约束。

    我就有点懵逼了

    1. 如果不用数据库的外键关联,那表之间应该怎么关联呢?
    2. 不用外键约束,怎么保证表的数据完整性和一致性的维护?
    53 条回复    2020-05-31 17:41:01 +08:00
    shintendo
        1
    shintendo  
       2019-09-16 10:55:03 +08:00
    说的是不用外键 [约束] ,关联还是那样关联
    cl903254852
        2
    cl903254852  
    OP
       2019-09-16 10:56:43 +08:00
    @shintendo 是我表达有问题,就是不用外键
    littlewing
        3
    littlewing  
       2019-09-16 10:56:54 +08:00 via iPhone
    业务层自己维护
    phx13ye
        4
    phx13ye  
       2019-09-16 10:59:03 +08:00   ❤️ 1
    代码自己保证呗,然后不做物理删除,美其名为互联网做法
    mingl0280
        5
    mingl0280  
       2019-09-16 10:59:37 +08:00
    业务层维护,好处是数据库服务器可以降低性能需求,坏处是容易弄炸掉关联。
    这种说法大部分是超高并发环境(都要减低数据库压力了,得有多少用户啊……),入门别管就可以了。
    jay0726
        6
    jay0726  
       2019-09-16 10:59:52 +08:00
    不用物理外键而是用逻辑外键
    Caballarii
        7
    Caballarii  
       2019-09-16 10:59:57 +08:00
    代码里用到的时候约束
    一致性完整性自己有空写脚本去对随便怎么都行
    数据库上留点没用的数据没什么大不了的
    love
        8
    love  
       2019-09-16 11:05:13 +08:00   ❤️ 2
    有没有约束和关联查询没有关系。

    当然没约束有产生无效 ID 的可能,但对绝大部分应用实际上不是问题。
    shintendo
        9
    shintendo  
       2019-09-16 11:19:43 +08:00
    @cl903254852 你表达没问题,我就是在回答你的问题
    taotaodaddy
        10
    taotaodaddy  
       2019-09-16 11:23:15 +08:00 via Android
    楼主确实要先说清楚是不用物理主键还是连逻辑主键都不用
    taotaodaddy
        11
    taotaodaddy  
       2019-09-16 11:25:21 +08:00 via Android
    啊,把“外”敲成“主”了
    nekolr
        12
    nekolr  
       2019-09-16 11:37:18 +08:00
    就是指建表的时候不建立外键。

    使用时还是正常联表查询,和有没有约束时是一样的。再说表之间的关联在逻辑上本来就是存在的,不需要定义。外键约束的作用是维护一致性和完整性,不使用外键,那就只能通过代码层面去保证完整性和一致性。
    Raymon111111
        13
    Raymon111111  
       2019-09-16 11:40:59 +08:00
    一致性业务逻辑去保证

    延迟检查补偿最终一致是一种常见的方案
    leo108
        14
    leo108  
       2019-09-16 11:50:50 +08:00
    楼上无脑推荐不用外键的,如果外键真这么没用,Mysql 为啥还需要设计这个东西?
    To 楼主,技术选型要看具体业务,不是阿里说不用外键,整个软件业就都不能用,你要想想别人为什么要这么规定,不用外键带来了什么收益,付出了什么代价,对你自己的业务来说代价和收益哪个更高?
    wysnylc
        15
    wysnylc  
       2019-09-16 11:57:46 +08:00
    @leo108 #14 外键带来的问题比解决的问题多,比如要删除 a 表数据但是该表有子表的外键那么就不能删除,这样会导致开发无比的冗余复杂,而在当前的互联网环境下没有这么多时间跟你磨蹭. 严谨和效率从来都是相克的
    目前我所知的外键环境只有银行,银行才需要每条数据的精准严谨,所以银行可以放弃效率
    但是互联网放弃效率等于百米赛跑你坐轮椅别人一路狂奔甩你 90 米
    zazalu
        16
    zazalu  
       2019-09-16 12:02:56 +08:00
    楼主是不是一时头晕想糊涂了,就算不使用外键这种"强"约束,也可以通过一些方式来实现“弱”约束从而达到关联的目的,当然这一切都是因为外键貌似影响性能以及纯粹的麻烦!- -
    Vegetable
        17
    Vegetable  
       2019-09-16 12:21:51 +08:00   ❤️ 1
    数据库往往是性能瓶颈,所以要给数据库减负,这是大前提.

    外键是一个数据库提供的功能,他需要数据库额外的开销对数据合法性进行检查,开销还不小,这就违背了上边说的大前提.

    所以这种可以不用数据库做的工作,尽量不用数据库做.不过注意,这么做不是永远正确的.
    littlewing
        18
    littlewing  
       2019-09-16 13:18:55 +08:00
    @phx13ye 还不是因为互联网穷,用不起 oracle 和 DB2
    Mosy
        19
    Mosy  
       2019-09-16 13:20:56 +08:00 via iPhone
    @wysnylc 大哥,你那里得知的消息银行不需要效率了?银行中间业务系统也不用外键,一天上亿笔交易处理还是需要处理效率的。
    lolizeppelin
        20
    lolizeppelin  
       2019-09-16 13:21:26 +08:00 via Android
    @wysnylc

    外键可以自动删除关联子健的
    cl903254852
        21
    cl903254852  
    OP
       2019-09-16 13:41:44 +08:00
    @nekolr 你说的对。但是这样的话,ER 图就用不了了,这也是不用数据库外键关联的缺点之一,也是我觉得很可惜的点
    cl903254852
        22
    cl903254852  
    OP
       2019-09-16 13:42:09 +08:00
    @jay0726 为了性能,牺牲了不少好东西,比如 ER 图
    cl903254852
        23
    cl903254852  
    OP
       2019-09-16 13:42:27 +08:00
    @wysnylc 赞同
    cl903254852
        24
    cl903254852  
    OP
       2019-09-16 13:43:09 +08:00
    @zazalu 你说的弱约束一般是指用代码控制吧
    qiyuey
        25
    qiyuey  
       2019-09-16 13:49:55 +08:00
    17 楼说的很对,数据库往往是性能瓶颈,所以使用逻辑外键替代物理外键,并不是说外键的概念有问题,而是实际工程发展出来的解法
    Mac
        26
    Mac  
       2019-09-16 14:10:40 +08:00 via Android
    先去搞懂 join 语句的运行逻辑。利用关键字段的关联写业务逻辑就行了。
    Austaras
        27
    Austaras  
       2019-09-16 14:52:32 +08:00
    @Mosy 业务量大和对性能要求高并不等同,银行等金融业里遇到的大部分性能问题都可以加钱解决
    wysnylc
        28
    wysnylc  
       2019-09-16 15:04:44 +08:00
    @Mosy #19 不需要效率不代表没有高性能,堆硬件和代码优化同样可以达到高性能
    效率是相对的,如果银行不使用外键关联强约束性能会更好,懂了吗?
    younfor
        29
    younfor  
       2019-09-16 15:04:48 +08:00
    楼主说的大概是数据库层面的物理外键吧。还是看业务场景吧,外键本身设计是在数据库层面实现强一致性和完整性数据约束的。如果你的正确性大于性能的话,可以使用,当然也会有维护成本。不用外键的话,也可以在业务逻辑层用程序代码控制,这个数据会和业务同步修改会有耦合性。
    wysnylc
        30
    wysnylc  
       2019-09-16 15:05:27 +08:00
    @lolizeppelin #20 那银行不敢让你写业务...谁敢这么删数据
    passerbytiny
        31
    passerbytiny  
       2019-09-16 15:09:10 +08:00
    @cl903254852
    首先,真正的 ER 图是业务模型,它需要先转换成逻辑模型,再转换成物理模型后,才能与数据库扯上关系。
    其次,即使是偷懒方式下的 ER 模型,也只需要保证正向工程( ER 图—>数据库结构)时刻可用,不需要保证反向工程总是可用,反向工程只是用来帮助你首次设计 ER 图的时候偷懒的,不是必选项。
    dog82
        32
    dog82  
       2019-09-16 15:10:48 +08:00
    在业务层自己写代码控制,不要用 mysql 的外键约束
    leo108
        33
    leo108  
       2019-09-16 15:13:39 +08:00
    @wysnylc 所以在你眼里只有互联网行业才用得着数据库了?看不见我回复里的『看具体业务』这么几个字?
    wangxiaoaer
        34
    wangxiaoaer  
       2019-09-16 15:34:52 +08:00 via Android
    想问下你们自己业务层做控制,那么关联查询后分页之类怎么做?

    难道业务层两个表全部查出来,然后交叉对比?
    xaplux
        35
    xaplux  
       2019-09-16 15:42:47 +08:00
    只是不用外键约束(比如 MySQL 的外键约束),又没有说不让用外键的那套逻辑,只不过这套逻辑在程序中控制了,ER 图该画的还是要画啊。该怎么表示外键的还是怎么表示就好了
    shintendo
        36
    shintendo  
       2019-09-16 15:51:41 +08:00
    @wangxiaoaer 在业务层维护约束,不是在业务层 JOIN 啊……
    wysnylc
        37
    wysnylc  
       2019-09-16 15:53:06 +08:00
    @leo108 #33 所以我明说了外键在银行和银行之外的区别,需要严谨的就得抛弃效率拥抱外键,需要效率就抛弃严谨抛弃外键
    我打的比方有问题?
    chinvo
        38
    chinvo  
       2019-09-16 15:54:12 +08:00 via iPhone
    @wysnylc #15 你需要 ON DELETE 和 ON UPDATE
    akira
        39
    akira  
       2019-09-16 15:57:41 +08:00
    刚入门别看这些 华丽花哨的东西,老老实实把数据库的基础知识概念学好了先。
    要不要外键,什么时候要 什么时候不要 这些是生产工作的事情 还不到你接触的时候
    workspace
        40
    workspace  
       2019-09-16 16:08:53 +08:00
    users --> id name age is_del
    class --> id name is_del

    class_user --> id class_id user_id is_del

    # 伪代码
    查找用户所在 class
    class_id = select class_id from class_user where user_id = ${need_query_user_id} and is_del = 0
    class = select * from class where id = class_id and is_del = 0
    查找 class 中的用户
    user_id_list = select user_id from class_user where class_id = ${need_query_class_id} and is_del = 0
    user_list = select * from users where id in (user_id_list) and is_del = 0
    ralph79
        41
    ralph79  
       2019-09-16 16:55:32 +08:00
    外键时约束,数据自身产生联系就好了,和建不建外键没有关系
    zazalu
        42
    zazalu  
       2019-09-16 17:00:03 +08:00
    @cl903254852 全部都是软件,全部都是代码,你说的这个代码控制,我觉得说的不太准确哈哈。 控制方式多种多样,随你怎么控制,关键还是在于性能哦!如果你说的这个“代码控制”它本身性能还不如直接用外键,那么又有何意义呢
    Variazioni
        43
    Variazioni  
       2019-09-16 17:07:21 +08:00
    业务层里自己判断啊。。。
    cl903254852
        44
    cl903254852  
    OP
       2019-09-16 17:16:14 +08:00
    @akira 我看到有人这么说了,就好奇为什么,就过来问问。🤣打扰了打扰了
    cl903254852
        45
    cl903254852  
    OP
       2019-09-16 17:19:00 +08:00
    @zazalu 大佬说的有道理。我说的代码控制是指 java 或 php 这类的服务端代码根据业务控制外键约束
    wangxiaoaer
        46
    wangxiaoaer  
       2019-09-16 17:32:32 +08:00 via Android
    @shintendo 我艹,我他么傻逼了。不好意思。
    chengyiqun
        47
    chengyiqun  
       2019-09-16 23:20:26 +08:00
    数据量大都那么做的吧, 逻辑外键, 业务层控制. 关联表多了, 数据量大了, 物理外键确实会降低并发, 同时, 不方便割接数据, 但是坏处就是容易产生脏数据.
    zomco
        48
    zomco  
       2019-09-17 07:06:35 +08:00 via Android
    我懵了,表 1 与表 2 不用外键关联的话,是如何用表 1 的第 n 行查询到表第 k,l 行的?是让表 1 冗余,表 1 和表 2 根据 ID 一一对应吗?
    zc1249274251
        49
    zc1249274251  
       2019-09-17 07:25:23 +08:00
    设计表的时候,部分冗余,做一些反范式化的设计
    linxiaojialin
        50
    linxiaojialin  
       2019-09-17 09:49:48 +08:00
    1.用不用外键都可以关联查询;
    2.数据的一致性、完整性:
    数据量小或者没用分布式的话,可以用外键约束;
    数据量大的话,建议在业务层约束;
    3.如何判断数据量大小:结合表的记录和实际业务逻辑的复杂度自行判断吧
    MrYELiex
        51
    MrYELiex  
       2019-09-17 10:53:20 +08:00
    主要还是因为物理外键在集群上维护性的问题 因为互联网业务场景下数据库大多都是集群 可能用户的一条用户信息在另一台机器上 而他同时下两个订单分别在两个机器上 这怎么维护外键
    johnsona
        52
    johnsona  
       2020-05-24 08:36:02 +08:00
    @workspace 子查询吗
    johnsona
        53
    johnsona  
       2020-05-31 17:41:01 +08:00
    @wysnylc 可是代码里面维护一致性反而更加磨蹭啊喂
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3484 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 04:48 · PVG 12:48 · LAX 21:48 · JFK 00:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.