素材牛VIP会员
MySQL数据库应不应该拿掉所有的外键约束?
 阿***c  分类:SQL代码  人气:861  回帖:4  发布于6年前 收藏

RT
拿掉外键好像是,能增加效率减少约束。

讨论这个帖子(4)垃圾回帖将一律封号处理……

Lv1 新人
十***刻 产品经理 6年前#1

当你需要分库分表的时候你就知道,在所有RDBMS里提供的所谓原子性一致性完整性保证基本上都是扯淡,也就持久性你还能指望一下,但也只是“指望”一下而已,最终还是要自己动手。
当然如果你确定一定以及肯定你永远不会有这方面的需求,系统级的保证当然越多越好,不过千万记得,面对MyISAM之类的Engine时,你呵呵一下一笑而过就好。

Lv4 码徒
23***om JS工程师 6年前#2

找到了这篇数据库外键的必要性
数据库外键的必要性,扯蛋!这个时候还来讨论这个问题,就像讨论“我们是否需要穿上衣服上街,还是要大家都在街上祼奔一样”。

从各主要数据库发展趋势

可以看出,大数据库像Orcle,MS SQL Server,……就不说了,它们一直都是。

你说 MySql 不支持,那是 MyISAM 表格式,现在它们默认都是 InnoDB 表格式,它是支持外键的;

你说 SQLite不支持,但它从 3.6.19 版本开始已支持了……

……

…… 只是你的懒惰和习惯而已!!! ……

大家喜欢使用外键吗?

http://www.itpub.net/thread-1313696-1-1.html

正方:代表人物newkid。

主要论点如下

原帖由 newkid 于 2010-6-10 22:48 发表
记得我不止一次在这里和别人争过这个问题了。
1. 你的程序再严谨也有可能出现BUG;你自己判断不如交给数据库判断,它做得又快又好。
大多数人的程序没有考虑并发问题。一旦考虑了就得手工加锁,效率很低。
数据可能绕过你的应用程序进入数据库。
2. 性能问题:难道你自己做就没有开销?
一个外键判断分摊到事务级别,开销可以忽略,用户完全没有察觉。
如果是批量导入数据,可以先暂时屏蔽外键,事后用NOVALIDATE选项快速恢复,前提是你的数据是干净的。
3. 举个麻烦的例子看看?
外键约束正是为了防止你乱来,这是给你的保护。
开车系安全带麻烦吧?有时候它能救你的命。
4. nyfor说过了可以用延迟约束。但根据我的经验没什么必要。凡是有外键则父亲数据必定先生成。比方说你的入库单,入库明细需要这个单号,那么父亲表(入库单)肯定要先生成。
此外,外键还会给CBO提供重要的信息,用来生成最优计划。

反方:代表人物qingyun。

主要论点如下

原帖由 qingyun 于 2010-6-10 13:32 发表
我不太喜欢外键,
原因:
1.程序逻辑,完整性,我会在存储过程或包等地方做严谨的判断;
2.性能问题,这是我最不喜欢用的关键原因,比如一个业务流水表,频繁插入数据,如果这个表身上有3外键,那么每次插入一条,就必须对这3个外键对应的3个表做相应的查找判断有无对应数据,如果这3个表也很大,那就这3个表的判断时间就很常,虽然外键指向的关联表的字段肯定是索引,但是我觉得很多时候,这样的判断本来就在程序里控制好了,通过外键再判断一次,就是降低性能;而且其实有的地方判不判断也无所谓的,但是用了外键,就必须化时间去判断,无论oracle内部多么优化外键对于数据的检索速度,它总是一个不小的消耗;
3.维护麻烦,很多公司的软件都是定制的,这种定制的东西,随意性相对较大,项目开发实施过程中,需要经常对表修修补补;还有就是业务逻辑有bug或者其他情况,需要经常手工维护数据,有错综复杂的外键关联着,很是麻烦;
4.不灵活,外键定死了两个表之间数据的先后生成关系,最常见的是单据主从表,有的时候,在生成单据的时候,是先生成明细,再生成主表;如果钉死了外键,这个就没法实现;
当然有些关键的业务,确实需要外键;
为什么说这个话题,我今天把项目数据库建立好后,用了很少的外键,周围同事说数据不严谨,需要错综复杂的那些相同字段名的外键都建立起来,这个我很不情愿;
比如这个数据库一共100个表,按他们的想法,外键就可能有300个;我晕,太教条主义了;
如果说让我建300个索引,我很乐意,因为提高运作效率的,而外键只是检测严谨性,对数据库的运作效率只有降低,没有任何提高的可能性;
其实这只是设计习惯的问题 ,有兴趣大家随便聊聊自己的习惯。

还有一个反方的声音有独特见解

一起放上来供大家参考

原帖由 ruideliang 于 2010-6-12 14:42 发表
外键是暴露的,程序是封闭的,同样是经过测试的程序和外键约束,人为因素造成约束失效的可能性谁大谁小,很明显,所以反对使用外键,因为与系统高可用性目的冲突

反!

外键是暴露的? 只要绕过你的应用程序登录数据库,还有什么不是暴露的?
那你说要不要主键?它也是暴露的,你随时可以DROP.
表结构呢?是不是暴露的?你随时可以修改。
这又和高可用性有什么关系?
同样是经过测试的程序和外键约束”:
外键不用测试。只要你的数据存在这种关系,一个DDL搞定。
外键同样也可以是封闭的。有一种东西叫做“授权”,不该看到的用户,什么也看不到!在我设计的系统中,客户端只能看到存储过程的接口。

数据库中主键和外键的设计原则

http://www.cnblogs.com/tianyamoon/archive/2008/04/02/1134394.html

主键和外键是把多个表组织为一个有效的关系数据库的粘合剂。主键和外键的设计对物理数据库的性能和可用性都有着决定性的影响。

必须将数据库模式从理论上的逻辑设计转换为实际的物理设计。而主键和外键的结构是这个设计过程的症结所在。一旦将所设计的数据库用于了生产环境,就很难对这些键进行修改,所以在开发阶段就设计好主键和外键就是非常必要和值得的。

主键:

关系数据库依赖于主键---它是数据库物理模式的基石。主键在物理层面上只有两个用途:

  1. 惟一地标识一行。
  2. 作为一个可以被外键有效引用的对象

基于以上这两个用途,下面给出了我在设计物理层面的主键时所遵循的一些原则:

  1. 主键应当是对用户没有意义的。如果用户看到了一个表示多对多关系的连接表中的数据,并抱怨它没有什么用处,那就证明它的主键设计地很好。
  2. 主键应该是单列的,以便提高连接和筛选操作的效率。
    注:使用复合键的人通常有两个理由为自己开脱,而这两个理由都是错误的。其一是主键应当具有实际意义,然而,让主键具有意义只不过是给人为地破坏数据库提供了方便。其二是利用这种方法可以在描述多对多关系的连接表中使用两个外部键来作为主键,我也反对这种做法,理由是:复合主键常常导致不良的外键,即当连接表成为另一个从表的主表,而依据上面的第二种方法成为这个表主键的一部分,然,这个表又有可能再成为其它从表的主表,其主键又有可能成了其它从表主键的一部分,如此传递下去,越靠后的从表,其主键将会包含越多的列了。
  3. 永远也不要更新主键。实际上,因为主键除了惟一地标识一行之外,再没有其他的用途了,所以也就没有理由去对它更新。如果主键需要更新,则说明主键应对用户无意义的原则被违反了。
    注:这项原则对于那些经常需要在数据转换或多数据库合并时进行数据整理的数据并不适用。
  4. 主键不应包含动态变化的数据,如时间戳、创建时间列、修改时间列等。
  5. 主键应当有计算机自动生成。如果由人来对主键的创建进行干预,就会使它带有除了惟一标识一行以外的意义。一旦越过这个界限,就可能产生认为修改主键的动机,这样,这种系统用来链接记录行、管理记录行的关键手段就会落入不了解数据库设计的人的手中。
Lv3 码奴
Go***ng 职业无 6年前#3
  1. 作为写了8年PHP的程序员来讲, 我个人的习惯是不使用外键。
  2. 因为我们所接触的绝大多数业务需求,并没有严谨到需要双层数据验证(第一层是在PHP代码里)。
    即使是对数据一致性稍有要求的电子商务网站,我也接触过只用MyISAM表的,除了程序逻辑本身经过严格的单元测试和使用场景测试去保证数据一致性之外,我们还准备了完善的logging系统,在pdo层面对站点数据的每一次CURD做日志,针对管理员和会员的每一个操作也做日志,方便意外情况的随时排查。
  3. 选型过程中没有使用Innodb的其它原因还包括:缓存的设计十分合理、命中率十分高,并且经过了数据验证,综合应用流量,我们可以大胆不去考虑锁表问题;外键确实增加了数据库开销,相对于我们站点的规模来讲,增加的开销无法忽略;绝大多数PHPJava前端人员水平良莠不齐,我们不想为数据库基础不好的同学做科普。
  4. 说句题外话,当一个应用需要考虑是否拿掉外键,提高效率的时候。需要重构代码或增加中间件(mongo, redis之类)以应付数据库开销了。
Lv6 码匠
驱***森 技术总监 6年前#4

如果需要切分数据表到不同的数据库里面时,就不能使用外键作为约束了

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取