MySQL外键约束简介

  InnoDB是目前MySQL中唯一支持外键的内置存储引擎,所以如果需要外键支持那选择 就不多了(PBXT也有外键支持)。 

  使用外键是有成本的。比如外键通常都要求每次在修改数据时都要在另外一张表中多执行一次査找操作。虽然InnoDB强制外键使用索引,但还是无法消除这种约束检査的开销。如果外键列的选择性很低,则会导致一个非常大且选择性很低的索引。例如,在一个非常大的表上有status列,并希望限制这个状态列的取值,如果该列只能取三个值——虽然这个列本身很小,但是如果主键很大,那么这个索引就会很大——而且这个索引除了做这个外键限制,也没有任何其他的作用了。

  不过,在某些场景下,外键会提升一些性能。如果想确保两个相关表始终有一致的数据,那么使用外键比在应用程序中检査一致性的性能要高得多,此外,外键在相关数据的删除和更新上,也比在应用中维护要更髙效,不过,外键维护操作是逐行进行的,所以这样的更新会比批量删除和更新要慢些。

  外键约束使得査询需要额外访问一些别的表,这也意味着需要额外的锁。如果向子表中写入一条记录,外键约束会让InnoDB检査对应的父表的记录,也就需要对父表对应记录进行加锁操作,来确保这条记录不会在这个事务完成之时就被删除了。这会导致额外的锁等待,甚至会导致一些死锁。因为没有直接访问这些表,所以这类死锁问题往往难以排査。

  有时,可以使用触发器来代替外键。对于相关数据的同时更新外键更合适,但是如果外键只是用作数值约束,那么触发器或者显式地限制取值会更好些。(这里,可以直接使用ENUM类型。)

  如果只是使用外键做约束,那通常在应用程序里实现该约束会更好。外键会带来很大的额外消耗。这里没有相关的基准测试的数据,不过我们碰到过很多案例,在对性能进行剖析时发现外键约束就是瓶颈所在,删除外键后性能立即大幅提升。

作者:小家电维修

相见有时,后会无期。

原文地址:https://www.cnblogs.com/lizexiong/p/15549062.html