我有一个包含两个表的数据库,当前每个表有 3 列。
Table_A:id
、uid
、url
Table_B:id
、uid
、url
id
是主键,在插入的每个新行上自动递增 1
。
我的问题是我还需要主键吗?我永远不会在数据库中查询id
。
uid
列只是为了分隔每个用户,因此每行不是唯一的。
Table_A
和 Table_B
将经常通过 uid
进行比较。
我有 uid
、url
索引,我预计该表可能会增长数十亿,而且我不想在 id
上浪费空间.
最佳答案
如果您使用 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 不创建隐式列。
回复您的评论:
我尽量不使用MyISAM。 MyISAM 比 InnoDB 更容易受到数据损坏的影响,并且通常 InnoDB 性能更好,因为它同时缓存数据和索引。确实,在某些情况下 MyISAM 可以使用更少的磁盘空间,但磁盘空间很便宜,我更愿意享受 InnoDB 的好处。
关于索引,如果您有PRIMARY KEY(uid, url)
,那么您将自动在这两列上拥有一个复合索引。无需在 uid 上创建额外的索引。
但是,如果您的查询仅搜索 url,而不查找特定的 uid,那么您需要在 url 上建立单独的索引。
我在演讲中详细讨论了索引设计:How to Design Indexes, Really
关于mysql - 主键自增,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14464837/