【问题标题】:primary key auto increments主键自动递增
【发布时间】:2013-01-22 17:46:36
【问题描述】:

我有一个包含两个表的数据库,目前每个表有 3 列。

Table_Aiduidurl

表_Biduidurl

id 是主键,在插入的每个新行上自动递增 1

我的问题是我还需要主键吗?我永远不会在数据库中查询iduid 列只是按用户分隔,因此它不是每行唯一的。 Table_ATable_B 会经常被uid 比较。 我有 uid, url 索引,我希望该表可能会增长数十亿,我不想在 id 上浪费空间。

【问题讨论】:

  • RDBMS 中的所有表都需要主键。但是,它不需要是专用的(“代理”)自动递增 ID。它可以是在表中的一个或多个列上形成的“自然”键,或者(取决于数据库引擎)两者的组合!

标签: mysql


【解决方案1】:

如果您使用 InnoDB,并且未声明主键列,InnoDB 将使用 6 字节整数为您创建一个。因此,您通过删除 id 列获得的唯一好处可能是用 8 字节 BIGINT 换取 6 字节隐式 PK 列。

原因是 InnoDB 表存储为 B 树,即基于主键的聚集索引。每个表都必须有一个用于组织此 B 树的列,即使它是隐式创建的列。

您还可以使用复合主键声明表:

CREATE TABLE Table_A (
  uid INT NOT NULL,
  url VARCHAR(100) NOT NULL,
  PRIMARY KEY (uid, url)
);

在这种情况下,主键的要求得到满足,InnoDB 不会创建隐式列。


你的cmets:

我尽量不使用 MyISAM。 MyISAM 比 InnoDB 更容易受到数据损坏的影响,并且通常 InnoDB 性能更好,因为它同时缓存了数据和索引。确实在某些情况下 MyISAM 可以使用更少的磁盘空间,但磁盘空间很便宜,我更愿意获得 InnoDB 的好处。

关于索引,如果您有PRIMARY KEY(uid, url),那么您将自动在这两列上拥有一个复合索引。无需在 uid 上创建额外的索引。

但是,如果您有单独搜索 url 的查询,而不寻找特定的 uid,那么您需要一个单独的 url 索引。

我在演讲中更多地谈论索引设计:How to Design Indexes, Really

【讨论】:

  • 感谢您 +1 的示例。我正在辩论使用 innodb 或 myisam。 uid会有很多数据的比较。我确实注意到,如果我使用 myisam,表大小会下降第三然后 innodb。
  • @Madbreaks 我还应该为 uid 和 url 添加索引吗?
  • 谢谢,我唯一与 uid-url 不同的查询是 table_b ,它“从 table_b 中删除 WHERE uid ='$uid” 但该表在比较之前只有临时行。
【解决方案2】:

技术上不会,尽管这是一种很好的做法,而且您永远不知道您未来的要求是什么。如果您最终需要一个独特的 id 列而没有,这可能是一个令人头疼的问题。在我看来,id 列上“浪费”的开销数量绝对值得。

此外,根据Table_ATable_b 之间的关系,您最终可能会有一个中间表来定义它们之间的关系(例如one-to-nanymany-to-many)。对于此类场景下的高效查询,唯一的id 列成为必需品。

【讨论】:

  • 好吧,id 设置为 255 字符,所以十亿多行会占用一些空间。我知道如果你没有,innodb 会创建一个。
【解决方案3】:

您不需要id 列,但在我看来,您的“主”键是uid-url

【讨论】:

  • 我将使用像 WHERE uid = '$uid' AND url = '$url' 这样的查询,你是对的,uid-url 永远不会有两行相同的行我如何将其设为主键?
  • @AbbyE 在创建语句中:PRIMARY KEY (uid, url)
猜你喜欢
  • 2013-09-28
  • 2017-02-10
  • 2018-11-23
  • 2019-08-07
  • 1970-01-01
  • 2015-05-11
  • 2012-12-08
  • 2012-03-13
  • 1970-01-01
相关资源
最近更新 更多