我有一个包含两个表的数据库,目前每个表都有 3 列。
表_A:id
,,,uid
url
表_B:id
,,,uid
url
是在插入的每个新行上自动递增的id
主键。1
我的问题是我还需要主键吗?我永远不会在数据库中查询id
. 该uid
列只是按用户分开,因此每行不是唯一的。
Table_A
并且Table_B
会经常被比较uid
。我已经索引了uid
,url
我希望该表可能会增长数十亿,我不想在id
.
我有一个包含两个表的数据库,目前每个表都有 3 列。
表_A:id
,,,uid
url
表_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 不创建隐式列。
回复您的评论:
I try not to use MyISAM. MyISAM is more susceptible to data corruption than InnoDB, and usually InnoDB performs better because it caches both data and indexes. It's true there are some cases where MyISAM can use less disk space, but disk space is cheap and I'd much rather get the benefits of InnoDB.
Regarding indexes, if you have PRIMARY KEY(uid, url)
then you automatically have a compound index over those two columns. No need to create an extra index on uid.
But if you have queries that search for url alone, without looking for a specific uid, then you need a separate index on url.
I talk more about index design in my presentation: How to Design Indexes, Really
从技术上讲不是,尽管这是一种很好的做法,而且您永远不知道您未来的要求是什么。如果您最终需要一个独特的id
列而没有,这可能是一个非常令人头疼的问题。在我看来,列上“浪费”的开销数量id
绝对值得。
此外,根据 和 之间的关系Table_A
,Table_b
您最终可能会有一个中间表来定义它们之间的关系(例如one-to-nany
,many-to-many
)。对于这种场景下的高效查询,唯一id
列成为必需品。
您不需要这些id
列,但在我看来,您的“主”键是uid-url