为什么选择二进制(16)PK而不是复合键?

时间:2015-11-01 03:32:06

标签: mysql npm

查看用于npm的下载计数的MySQL模式:https://github.com/npm/download-counts/blob/master/test/schema.sql#L3,为什么他们会选择二进制PK 一个唯一索引(包,日)使用(package,day)元组作为复合键?

使用复合键作为唯一键(丢弃二进制(16)键)是否存在性能/存储问题?

1 个答案:

答案 0 :(得分:1)

这个设计决定通常是衡量权衡的结果。

就存储而言,在更一般的情况下,可能有其他表具有对表的外键引用。该主键值将需要存储为参考。如果主键是复合键,则所有主键列也需要存储在引用表中。使用较短的单列作为主键意味着只需要将较短的值存储在引用表中。

此外,如果表上有任何二级索引,(在InnoDB中)主键值也存储在二级索引中,作为对该行的引用。 (在InnoDB中,主键用作群集密钥。)

一些设计师认为"理想"首要的关键。这些并不是主键的所有硬性要求,但出于以下几个原因这些是可取的:

  • 唯一(无重复值)
  • 非null(将始终指定值)
  • 不可变(一个已分配,不会更改)
  • 匿名(不带#34;含义")
  • simple(单列,本机数据类型)

如果主键中的任何列具有某些含义,则可能导致需要允许更改主键中的列。在性能方面,更新主键可能意味着重定位表中的行,并更改为二级索引。这也可能导致需要添加另一个不可变标识符,以简化与其他系统的集成。

在所有表中遵循主键(名称和数据类型)的一致模式,这是一个一致的模式,可以为开发人员带来好处,特别是在ORM框架中。

如果所有表都有一个名为id的单个列的主键,所有相同的数据类型,那么这就是一致的模式,简化了一些开发模式。通常,外键列采用referenced_table_name_id之类的名称。在SQL中,这会导致一致的连接模式,例如

   FROM foo
   JOIN bar
     ON bar.foo_id = foo.id

遵循此模式,奇数或异常SQL看起来很奇怪或异常。使用"错误"的SQL连接谓词看起来也很奇怪......例如。

    FROM foo f
    JOIN bar b
      ON foo.id = bar.id 

(看起来像主键与主键匹配)

    FROM foo f
    JOIN bar b
      ON foo.somecol = bar.somecol

(从查看SQL看起来,似乎不明确哪个表是父表,哪个表是子表...哪个表是somecol的主键?

总而言之,做出设计决策可能有很多原因。我提供了一些简短列表,列出了设计人员/开发人员可能选择使用名为id的单个短列作为此表主键的一些原因。