我记得在播客014中听到Joel Spolsky提到他几乎从未使用过外键(如果我没记错的话)。然而,对我来说,它们对于避免数据库中的重复和后续数据完整性问题非常重要。

人们是否有一些可靠的理由(以避免与Stack Overflow原则一致的讨论)?

编辑:“我还没有创建外键的理由,所以这可能是我真正建立一个外键的第一个理由。”


当前回答

更大的问题是:你会戴着眼罩开车吗?如果你开发一个没有参考约束的系统就是这样。请记住,业务需求会改变,应用程序设计会改变,代码中相应的逻辑假设也会改变,逻辑本身也会被重构,等等。一般来说,数据库中的约束是在当代逻辑假设下放置的,对于特定的逻辑断言和假设集似乎是正确的。

在应用程序的整个生命周期中,引用检查和数据检查约束控制通过应用程序收集的数据,特别是当新需求驱动逻辑应用程序更改时。

从实时事务处理系统的角度来看,外键本身不会“提高性能”,也不会显著“降低性能”。然而,在大容量“批处理”系统中,约束检查存在一个聚合代价。这就是实时和批量事务处理的区别;批处理——通过约束检查,按顺序处理的批处理的总成本会对性能造成影响。

在一个设计良好的系统中,数据一致性检查将在处理批处理之前完成(然而,这里也有相关的成本);因此,加载时不需要外键约束检查。事实上,所有的约束,包括外键,都应该暂时禁用,直到批处理完成。

QUERY性能——如果表是在外键上连接的,那么要认识到外键列不是索引的事实(尽管根据定义,各自的主键是索引的)。通过索引一个外键,也就是索引任何键,在索引上连接表有助于提高性能,而不是通过连接一个带外键约束的非索引键。

Changing subjects, if a database is just supporting website display/rendering content/etc and recording clicks, then a database with full constraints on all tables is over kill for such purposes. Think about it. Most websites don’t even use a database for such. For similar requirements, where data is just being recorded and not referenced per say, use an in-memory database, which does not have constraints. This doesn’t mean that there is no data model, yes logical model, but no physical data model.

其他回答

我同意德米特里的回答,说得很好。

For those who are worried about the performance overhead FK's often bring, there's a way (in Oracle) you can get the query optimiser advantage of the FK constraint without the cost overhead of constraint validation during insert, delete or update. That is to create the FK constraint with the attributes RELY DISABLE NOVALIDATE. This means the query optimiser ASSUMES that the constraint has been enforced when building queries, without the database actually enforcing the constraint. You have to be very careful here to take the responsibility when you populate a table with an FK constraint like this to make absolutely sure you don't have data in your FK column(s) that violate the constraint, as if you do so you could get unreliable results from queries that involve the table this FK constraint is on.

我通常在数据集市模式中的某些表上使用这种策略,但在集成登台模式中不使用。我要确保复制数据的表已经强制执行了相同的约束,或者ETL例程强制执行了该约束。

我一直认为不用它们是懒惰的表现。我被教导应该一直这样做。但后来,我没有听乔尔的讨论。他也许有充分的理由,我不知道。

From my experience its always better to avoid using FKs in Database Critical Applications. I would not disagree with guys here who say FKs is a good practice but its not practical where the database is huge and has huge CRUD operations/sec. I can share without naming ... one of the biggest investment bank of doesn't have a single FK in databases. These constrains are handled by programmers while creating applications involving DB. The basic reason is when ever a new CRUD is done it has to effect multiple tables and verify for each inserts/updates, though this won't be a big issue for queries affecting single rows but it does create a huge latency when you deal with batch processing which any big bank has to do as daily tasks.

最好避免fk,但它的风险必须由程序员来处理。

我可以看到使用外键的一些原因(有人提到,孤立行很烦人),但我也从不使用它们。对于一个相对正常的DB模式,我不认为它们是100%需要的。约束是好的,但我认为通过软件来实施约束是更好的方法。

亚历克斯

我不得不在这里第二多的评论,外键是必要的项目,以确保你有完整的数据。ON DELETE和ON UPDATE的不同选项将允许你绕过一些人们在这里提到的关于它们的使用的“下降”。

我发现在我99%的项目中,我会使用FK来加强数据的完整性,然而,在很少的情况下,我的客户必须保留他们的旧数据,不管它有多糟糕....但后来我花了很多时间写代码,只得到有效的数据,所以它变得毫无意义。