我有一个包含两个表的数据库,目前每个表有3列。
Table_A :id
,uid
,url
Table_B :id
,uid
,url
id
是在插入的每个新行上按1
自动递增的主键。
我的问题是我还需要主键吗?我永远不会在id
查询数据库。
uid
列只是为每个用户分隔,因此每行不是唯一的。
Table_A
和 Table_B
经常会uid
进行比较。
我已将uid
,url
编入索引,我希望该表能够以数十亿的速度增长,而且我不想在id
上浪费空间。
答案 0 :(得分:2)
如果您使用InnoDB,并且未声明主键列,InnoDB将使用6字节整数为您创建一个。因此,通过删除id列获得的唯一事情可能是为6字节隐式PK列交换8字节BIGINT。
原因是InnoDB表存储为B树,这是一个基于主键的聚簇索引。每个表必须有一个用于组织这个B树的列,即使它是一个隐式创建的列。
您还可以声明一个包含复合主键的表:
CREATE TABLE Table_A (
uid INT NOT NULL,
url VARCHAR(100) NOT NULL,
PRIMARY KEY (uid, url)
);
在这种情况下,满足主键的要求,InnoDB不会创建隐式列。
重新评论:
我尽量不使用MyISAM。与InnoDB相比,MyISAM更容易受到数据损坏的影响,并且InnoDB通常表现更好,因为它会缓存数据和索引。确实有些情况下MyISAM可以使用更少的磁盘空间,但磁盘空间很便宜,而且我更愿意从InnoDB中获益。
关于索引,如果你有PRIMARY KEY(uid, url)
,那么你自动拥有这两列的复合索引。无需在uid上创建额外的索引。
但是如果你有查询单独搜索url而不查找特定的uid,那么你需要在url上有一个单独的索引。
我在演示文稿中详细介绍了索引设计:How to Design Indexes, Really
答案 1 :(得分:1)
技术上不行,虽然这是一种很好的做法,但你永远不知道未来的要求是什么。如果您最终需要一个唯一的id
列而没有一列,则可能是一个令人头疼的问题。在我看来,id
列上“浪费”的开销是绝对值得的。
此外,根据Table_A
和Table_b
之间的关系,您最终可能会有一个中间表来定义它们之间的关系(例如one-to-nany
,many-to-many
)。对于此类方案中的高效查询,唯一的id
列成为必需。
答案 2 :(得分:0)
您不需要id
列,但在我看来,您的“主要”键是uid-url