这是我最近一直在考虑的另一个。 我们在之前的讨论中得出结论:“自然主键是坏的,人工主键是好的。” 之前使用Hibernate我已经看到Hibernate默认为所有表创建一个序列。起初我对此感到困惑,你为什么要这样做。但后来我看到了它使父母和孩子联系起来的优势。由于没有表具有相同的主键值,因此意外地将父项与不是子项的表链接不会产生任何结果。
有没有人看到这种方法的任何缺点。我只看到一个:你的数据库中不能有超过999999999999999999999999999的记录。
答案 0 :(得分:11)
所有代码从单个序列中获取值可能会出现性能问题 - 请参阅this Ask Tom thread。
答案 1 :(得分:7)
根据数据库中序列的实现方式,始终点击相同的序列可能会更好或更差。当只有少数或仅一个线程请求新值时,将不会出现锁定问题。但是糟糕的实施可能会导致拥堵。
另一个问题是回滚事务:序列不会被回滚(因为其他人可能已经请求了更高的值),因此您可能会有很大的间隙,这会比您预期的更快地占用您的数字空间。 OTOH,需要一些时间才能吃掉2到40亿个ID(如果你“只”使用32位(签名)的内容),所以在实践中它很少成为问题。
最后,如果必须,您无法轻松重置序列。但是如果您需要重启序列(例如,自午夜以来的记录数),您可以告诉Hibernate创建/使用第二个序列。
一个主要优点是您可以通过ID唯一地识别数据库中任何位置的对象。这意味着您可以严格删除您在生产系统中编写的日志信息,如果您只拥有该ID,仍然可以找到一些信息。
答案 2 :(得分:5)
我更喜欢每张桌子有一个序列。这来自一个普遍观察:一些表(“主表”)具有相对较小的行数并且必须“永久”保持。例如,ERP中的客户表。
在其他表(“事务表”)中,永久生成许多行,但在一段时间之后,这些行可以存档(或简单地删除)。最极端的例子是用于调试目的的跟踪表;它可能会以每秒数百行的速度增长,但几天后每一行都会过时。
主表中的小ID使得直接在数据库上工作变得更容易,例如:用于调试目的。
select * from orders where customerid=415
VS
select * from orders where customerid=89461836571
但这只是一个小问题。更大的问题是骑自行车。如果对所有表使用一个序列,则根本无法让它重新启动。每个表有一个序列,您可以在归档或删除旧数据时重新启动事务表的序列。主表几乎没有问题,因为它们变得慢得多。
我认为对所有表只有一个序列没什么价值。到目前为止所说的论点并不能说服我。
答案 3 :(得分:2)
使用单个序列有几个缺点: -
一个优点可能是您可以确定不同表中插入的顺序。
答案 4 :(得分:1)
当然,单序列与单序列每表的方法有利有弊。就个人而言,我发现能够为行分配一个真正唯一的标识符,使每个id列成为一个uuid,足以获得超过任何缺点的好处。正如Aaron D.简洁地写道:
您可以通过ID
唯一地识别数据库中任何位置的对象
而且,对于大多数应用程序,由于Hibernate3批处理IMPORT语句的方式,除非大量记录争夺相同的数据库资源(SELECT hibernate_sequence.nextval FROM dual),否则这不会成为性能瓶颈。
此外,Grails的最新版本(1.2)不支持此序列映射。虽然在Grails 1.1(!)中得到了支持。它现在需要继承Hibernate方言类之一作为变通方法。
对于使用Grails / GORM的人,请查看此JIRA条目: