我有一张用于记录许可证使用情况的表格。每个许可证使用都需要与用户和主机相关联。表定义如下所示。
create table if not exists per_user_fact
(
per_user_fact_id int unsigned not null auto_increment,
time_of_day char(16) not null,
license_served_id smallint unsigned not null,
license_hours numeric(10,2) not null,
role_name varchar(64) null,
user varchar(128) not null,
host varchar(128) not null,
primary key (per_user_fact_id),
foreign key (license_served_id) references served_license(served_license_id),
foreign key (user, host) references user_host(username, hostname)
);
我想规范化这个表,以便将重复的用户/主机值移动到这样的新表中。
create table if not exists user_host
(
username varchar(64) not null,
hostname varchar(128) not null,
primary key (username, hostname)
);
对于 user_host 表,我应该选择哪种主键 - 自然或代理?我可以想到以下控制因素。
请告知。
答案 0 :(得分:6)
即使在这种情况下,我也非常喜欢使用代理主键。当您加入群集主键时,额外连接的开销可以忽略不计。
此外,假设username
和hostname
(一起)长于4个左右的字符,代理键可以节省空间。实际上,您可能会发现代理键导致更快的查询,因为per_user_fact
中的数据较小。较小的表占用的数据页较少,导致I / O较少。
代理键的另一个优点是可以在不修改任何其他表的情况下更改用户名和主机名。如果您使用数据字段进行连接,那么修改这些值需要更新多个表 - 这是一个更麻烦的操作。
我也喜欢代理身份/序列/自动增量键,因为它们也捕获表中的插入顺序。当然,还有其他方法(我的表通常有一个CreatedAt
列,默认为插入时间)。但是,代理键也可以扮演这个角色。
这些原因并不构成问题的“正确”答案。没有使用代理人的正当理由。但对我来说,几乎所有的桌子都有这样的主键。
答案 1 :(得分:0)
鉴于问题中说明的情况,我将第二次使用代理密钥。虽然自然PK将在索引编制方面给您带来一些优势,但出于所有实际目的,使用替代代理将提供更多优势。
代理人可使您的表更苗条,为您提供审计的可能性等。