为什么组合键休眠灰心?(Why are composite keys discouraged in

2019-07-17 17:55发布

这是从休眠官方教程 :

有一种替代<composite-id>声明允许与复合键访问遗留数据。 它的使用是严格禁止的其他任何东西。

组合键为什么不鼓励? 我使用的是3列的表格,所有列的外键,并一起形成一个主键是在我的模型建立有意义的关系考虑。 我不明白为什么这是一个坏主意,espicially,我将使用他们的索引。

有什么办法呢? 创建一个额外的自动生成的柱,并使用它作为主键? 我还需要查询反正我3列!?

总之,为什么这种说法是真的吗? 什么是更好的选择吗?

Answer 1:

他们劝阻他们有以下几个原因:

  • 他们使用麻烦。 每当你需要引用一个对象(或行),为eexample在Web应用程序的时候,你需要传递3个参数,而不只是一个。
  • 他们是低效的。 而不是简单地散列的整数,数据库需要散列3列的复合物。
  • 它们会导致错误:开发商必然实现主键类的equals和hashCode方法不正确。 或者,他们使它可变的,一旦修改存储在一个HashSet或HashMap中的价值
  • 他们污染的模式。 如果另一个表需要引用这3列的表格,就需要有3列,而不是仅仅作为一个外键。 现在假设你遵循相同的设计,使这个新表的主键,这3列外键的一部分,你很快就会有一个4列主键,并在接下来的表,然后有5列PK,等。等等,从而导致数据的重复,一个肮脏的架构。

另一种方法是有一个单一的柱,自动生成的主键,除了其他三列。 如果你想三列的元组独特的,然后使用一个唯一约束。



Answer 2:

即使是 - 也许 - 来不及回答你的问题,我想在这里给就需要另一个角度来看(较温和的希望)(难道真是一个提醒?)的Hibernate使用代理键。

首先 ,我想成为这样的事实, 代理键(人工自动生成的)和自然键(与域名含义列(S)组成) 各有 利弊清晰。 我不是说,一点键式是优于其他。 我想说,根据您的要求,自然键可能比那些替代品,反之亦然一个更好的选择。

在自然键神话

  1. 复合键比代理键效率较低。 没有! 这取决于所使用的数据库引擎:
    • 神谕
    • MySQL的
  2. 自然键并不在现实生活中确实存在。 很抱歉,但它们确实存在! 在航空业,例如,下面的元组将始终是唯一的关于一个给定的定期航班(航空公司,departureDate,FLIGHTNUMBER,operationalSuffix)。 更一般地,当一组业务数据的保证是由给定的标准唯一那么这组数据是[好]天然关键候选。
  3. 自然键“污染模式”子表。 对我来说,这更是一个比一个真正的问题的感觉。 具有的各2个字节的4列主键可能比的11个字节的单个列更有效。 此外,4列可以(where子句中通过使用4列)被用来直接查询子表没有加入到父表。

代理键的缺点

代理键:

  1. 性能问题的来源:
    • 它们通常使用自动递增列这意味着执行:
      • 一个往返,每次你想获得一个新的ID数据库(我知道,这可以通过使用缓存或[SEQ]希洛相似的算法,但仍然这些方法都有自己的缺点加以改进)。
      • 如果有一天你需要从一个架构将数据移动到另一个(这相当经常发生在我的公司至少),那么你可能会遇到的ID冲突问题。 是的,我知道,你可以使用的UUID,但那些需要持续32个十六进制数字! (如果你关心数据库的大小,然后它可能是一个问题)。
      • 如果您正在使用您的所有代理键一个序列,然后 - 肯定的 - 你最终会与您的数据库上的竞争。
  2. 容易出错。 序列具有MAX_VALUE限制,以便 - 作为一个开发人员 - 你必须把注意以下事实:
    • 您必须循环的序列(当最高值达到它可以追溯到1,2,...)。
    • 如果你正在使用你的数据序列进行排序(一段时间内),那么你必须处理循环的情况下(ID为1列可能是新的比一行内径最大价值 - 1)。
    • 确保你的代码(甚至是你的客户,因为它应该是一个内部ID这是不应该的接口),支持您用来存储你的序列值32B / 64B整数。
  3. 他们不保证不重复的数据。 你总是可以有2行所有相同的列值,但具有不同的生成值。 对我来说,这是从一个数据库设计点代理键问题。
  4. 更多维基百科...

为什么休眠喜欢/需要代理键?

如Hibernate参考Java Persistence中指出:

经验更丰富的Hibernate的用户使用saveOrUpdate()方法专门; 它更容易让Hibernate自行决定什么是新的,什么是旧的,尤其是在混合状态对象的更复杂的网络。 独家saveOrUpdate()方法的唯一(不算严重),缺点是有时无法猜测的一个实例是否兵不血刃一个SELECT在数据库 - 例如,当一个类被映射与自然的复合键和旧的或新没有版本或者时间戳属性。

限制的一些表现(这是怎么样,我想,我们应该称呼它),可以发现在这里 。

结论

请不要太平方你的意见。 使用自然键时,它是相关的这样做,使用代理键时,它是更好地使用它们。

希望这个帮助别人!



Answer 3:

我会从设计角度考虑问题。 这不只是如果休眠认为他们好还是坏。 真正的问题是: 是自然键很好的候选人是好的标识符我的数据?

在你的商业模式,今天,它可以方便的通过一些数据来确定一条记录,而是商业模式演进的时间。 当这些发生时,你会发现你的自然键不适合了唯一标识您的数据。 并与其他表参照完整性,这将使事情更难改变。

有一个替代的PK是方便,因为它没有链接你的数据在存储识别 你的商业模式结构

自然键不能从一个序列生成的,并且不能由它的数据中识别数据的情况下是更加频繁。 这是一个证据表明,自然键从存储密钥不同,它们不能被视为一般的(和好)的办法。

使用代理键简化了应用程序和数据库的设计。 他们更容易使用,更高性能,并且做得很完美。

自然键带来的只是缺点:我想不出一个单一的优势,利用自然键。

这么说,我觉得休眠与自然的(组成)键没有真正的问题。 但是,你可能会发现一些问题(或错误)有时,和问题与文件或者试图得到帮助,因为休眠社会的广泛承认代理键的好处。 因此,准备你为什么选择复合键一个很好的答案。



Answer 4:

如果Hibernate文档被正确的理解:

“还有一个另外的<composite-id>允许访问遗留数据复合主键声明。它的使用是严格禁止的其他任何东西。”

在主题5.1.4。 ID标签的XML <id>这使得太快我们可以得出结论,休眠文件不鼓励使用所取得的主键映射<composite-id>而不是<id> XML标记为复合主键映射和NOT作出任何参考负使用复合主键。



Answer 5:

与数据库作为一种工具开发的应用程序肯定是更有利于保持对代理键的工作流程,使用群集索引查询优化。

特殊照顾并不需要但数据仓库和OLAP风格系统,利用一个巨大的事实表,以配合尺寸的代理键一起进行。 在这种情况下,数据指示可以用来保持记录的仪表板/应用程序。

因此,而不是一个方法是优于另一种,也许它是一个指令是有利的,另外,重点建设:你会不会很容易开发一个Hibernate应用程序能够利用到SSAS系统实例的直接访问。

我开发使用这两个按键混合物,感觉实现了坚实的星形或雪花的图案与聚簇索引的替代品通常是我的第一选择。

所以,到了OP的问候和其他寻求通过:如果你想留分贝不变的开发(其休眠专业) - 利用替代方法,并在数据读取趋于缓慢,或者你发现某些查询沥干性能,恢复到特定的数据库,并添加复合,聚集索引是优化查询顺序。



文章来源: Why are composite keys discouraged in hibernate?