主键应该是auto_increment吗?

oms*_*iga 3 database database-design

我知道在设计表时使用主键更好.

但我想知道何时设计一个主键,需要设置auto_increment?

如果完成,有什么好处?

我听,这可以保持b树的稳定,但我不知道为什么?

如果table有一个唯一列,那么将唯一列设置为主键或添加新列'id'作为auto_increment主键更好?

你能帮助我吗?谢谢.

Bra*_*vic 6

我知道在设计表时使用主键更好.

实际上,无密钥表是多集(因为它允许重复),因此不是严格的关系(这是一个集合),因此您的数据库实际上不是"关系".

请注意,"primary"(PRIMARY KEY)和"alternate"(UNIQUE约束)键在逻辑上是等效的.

但我想知道何时设计一个主键,需要设置auto_increment?

您实际上是在问多个问题:

  1. 我应该创建一个密钥吗?
  2. 如果是,我应该创建一个代理键吗?
  3. 如果是,它应该是整数吗?
  4. 如果是,我应该让它自动递增吗?

(1)的答案是"几乎总是".有一些非常罕见的情况,数据不是"重要",你可能会因为性能原因而跳过它,但这种情况非常罕见.

(2)的答案是"它取决于" - 主要的利弊可以在这里找到.

(3)的答案取决于您是否需要独立于数据库生成密钥(例如,在断开连接时,或在连接到不同的数据库时).如果是,您可以使用GUID(显然不能自动递增,但可以独立生成).如果不是,那么你可以使用整数 - 它们更紧凑,通常更快.

最后,如果你达到(4),那么你几乎肯定会想让它自动递增,原因如下所述.

如果完成,有什么好处?

  • 使整数代理键自动递增的主要好处是多个并发客户端永远不会收到相同的生成值.如果您只是尝试SELECT MAX(ID) + 1 FROM ...,则无法保证其他客户端不会同时尝试执行相同的操作,并最终得到相同的结果(随后导致密钥违规).
  • 另一个好处是DBMS将使用高度优化的代码路径来生成新的唯一值.
  • 缺点是自动增量机制通常不是事务感知的:如果生成新的ID值然后ROLLBACK事务,则不会再次生成该值.话虽如此,代理键没有任何意义(如果有的话,它们不会是代理),所以这样的"漏洞"是无关紧要的.

如果table有一个唯一列,那么将唯一列设置为主键或添加新列'id'作为auto_increment主键更好?

如果属性在"逻辑级别"本质上是唯一的,则必须使相应的表列唯一(通过PRIMARY KEY或UNIQUE约束),无论您是否稍后决定添加代理键.


Bil*_*win 5

我想知道何时设计主键,需要设置auto_increment?

不,这不是绝对必要的.有些情况下,自然键很好.

如果完成,有什么好处?

使用自动增量代理键的优点:

  • 代理键永远不需要更改,即使表中的所有其他列都可以更改.
  • 当您同时插入多个用户时,RDBMS更容易确保自动增量键的唯一性,而无需锁定和没有竞争条件.
  • 使用整数是可用于主键的最紧凑的数据类型,因此它导致的索引比使用长字符串的索引小.
  • 插入B树索引的效率(见下文).
  • 当唯一的其他候选键由多列组成时,使用单列而不是多列引用行更简单,更整洁.

使用自然键的优点:

  • 该列对于实体具有一些含义,例如电话号码.您不需要为代理键存储额外的列.
  • 使用外键引用自然主键的其他表获得有意义的值,因此它们可以避免连接.例如,如果要获取颜色名称,则需要进行shoes引用表colors.但是如果使用颜色名称作为主键colors,则该值已经是shoes表的一部分.

不需要代理自动增量键的其他情况:

  • 您已经拥有了为表提供候选键的其他列(无论是代理键还是自然键)的组合.在多对多表中找到了一个很好的例子.如果表将电影映射到演员,即使主键引用了电影和演员,那么您已经拥有这两列的候选键,并且您不需要另一个自动增量列.

我听,这可以保持b树的稳定,但我不知道为什么?

将值插入B树中间的任意位置可能会导致索引的重组成本高昂.

这里有一个动画示例:http://www.bluerwhite.org/btree/

查看示例"将密钥33插入B树(带拆分)",其中显示了将值插入到溢出它的B树节点中的步骤,以及B树响应的内容.

现在想象一下,示例说明只显示B树的底部更深(就像索引B树的情况一样有数百万个条目),填充父节点本身就是溢出,并强制拆分操作继续向上运行树中的更高级别.如果已经填充了树顶部的所有祖先节点,这可以一直持续到树的最顶层.

由于节点分裂并且必须重新构建,它们可能需要更多空间,但它们存储在数据库文件的某些页面上,其中没有空余空间.因此,存储引擎必须将部分索引重定位到文件的另一部分,并且可能仅针对单个INSERT重写大量索引页.

自动增量值自然总是插入B树的最右边.正如@ BrankoDimitrijevic在下面的评论中指出的那样,这并不会降低它们导致如此费力的节点拆分和重组到索引的可能性.但是B树实现代码可以通过其他方式针对这种情况进行优化,而有些则可以.

如果table有一个唯一列,那么将唯一列设置为主键或添加新列'id'作为auto_increment主键更好?

如果唯一列也是非可空的,则可以将其用作主键.主键要求所有列都不可为空.