查看用于npm的下载计数的MySQL模式:https://github.com/npm/download-counts/blob/master/test/schema.sql#L3,为什么他们会选择二进制PK 和一个唯一索引(包,日)使用(package,day)元组作为复合键?
使用复合键作为唯一键(丢弃二进制(16)键)是否存在性能/存储问题?
答案 0 :(得分:1)
这个设计决定通常是衡量权衡的结果。
就存储而言,在更一般的情况下,可能有其他表具有对表的外键引用。该主键值将需要存储为参考。如果主键是复合键,则所有主键列也需要存储在引用表中。使用较短的单列作为主键意味着只需要将较短的值存储在引用表中。
此外,如果表上有任何二级索引,(在InnoDB中)主键值也存储在二级索引中,作为对该行的引用。 (在InnoDB中,主键用作群集密钥。)
一些设计师认为"理想"首要的关键。这些并不是主键的所有硬性要求,但出于以下几个原因这些是可取的:
如果主键中的任何列具有某些含义,则可能导致需要允许更改主键中的列。在性能方面,更新主键可能意味着重定位表中的行,并更改为二级索引。这也可能导致需要添加另一个不可变标识符,以简化与其他系统的集成。
在所有表中遵循主键(名称和数据类型)的一致模式,这是一个一致的模式,可以为开发人员带来好处,特别是在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
的单个短列作为此表主键的一些原因。