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

标签 mysql npm

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

按其规模使用复合 key 作为唯一 key (删除二进制(16) key )是否存在性能/存储问题?

最佳答案

此设计决策通常是权衡权衡的结果。

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

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

一些设计者考虑了“理想”主键的一些理想属性。这些并不是主键的全部硬性要求,但出于以下几个原因,这些要求是可取的:

  • 唯一(无重复值)
  • 非 null(始终会分配一个值)
  • 不可变(已分配,不会更改)
  • 匿名(没有“含义”)
  • 简单(单列,原生数据类型)

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

在所有表中遵循主键(名称和数据类型)的一致模式,这种一致的模式可以为开发人员带来好处,尤其是在 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 的单个短列作为此表的主键的一些原因。

关于mysql - 为什么选择二进制 (16) PK 而不是复合 key ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33458939/

相关文章:

PHP/MySQL : Only able to insert values into first row

mysql - 使用两列计算总量,百分比?

docker - 如何在 docker 中安装全局 npm 依赖项?

node.js - 设置 npm config proxy ubuntu 后,npm 不起作用

node.js - Npm 脚本 - 关键 css

php - 处理共享主机上的 MySql 'Too many connections' 错误

php - Mysql 查询输出到 var data [,,,] 数组中

angularjs - 如何在客户端使用Node模块?

PHP MySQL 更新大型数据库时超时

angularjs - 在 grunt 调试后保存代码时出现 .Fatal 错误 : grunt. util._.contains 不是函数