在同一个父表中使用两个外键是否有任何意义,以避免内连接?
table:user_profile
id1, userid, username, firstname
table:user_hobby1
id2, userid(fk), hobby, movies
table:user_hobby2
id3, userid(fk), firstname(fk), hobby, movies
我想从上表中选择所有名字和爱好。我不确定user_hobby1或user_hobby2在性能方面是否是最好的设计?一个添加额外的外键,另一个需要加入。
查询1:
Select firstname, hobby
from user_hobby2;
查询2:
Select p.firstname, h.hobby
from
user_profile p
inner join user_hobby1 h on u.userid=h.userid;
答案 0 :(得分:0)
将用户表中属性的值复制到业余爱好者表中并不是外键",这就是冗余。
我们的性能目标通常不会遇到避免JOIN操作的方法,这是关系数据库运行的正常部分。
我将标准化设计作为第一次切割。每个属性应该依赖于密钥,整个密钥,以及除密钥之外的任何内容。 "名字"属性取决于用户的id,而不是业余爱好。
有时,我们通过在数据库中引入冗余来获得性能优势。我们必须以受控的方式做到这一点,并确保我们不会得到更新异常。 (如果" firstname"属性的值已更新,请考虑我们要应用的更改...我们是否对用户表,user_hobby表或两者进行了更改。
可能,"名字"在用户表中不是唯一的,所以我们绝对不希望外键引用该列;我们希望引用用户表的外键引用表的PRIMARY KEY。
如果user_hobby只与一个用户相关,那么在user_hobby和user之间定义两个外键是没有意义的。我们只需要一个外键...我们只是将用户表中的id存储在user_hobby表中。
答案 1 :(得分:0)
如果你在user_hobby2中有两个FK,那么你只能确保user_profile中存在userid和username,但是你无法确保哪个用户ID与给定的用户名一致。
如果你使用(userid,username)复合FK,那么你将保证每个元组的一致性,但是复合FK通常更难以处理。根据更新和删除级联的行为,我看到mysql触发它们并拒绝从父级删除。
除此之外......保持复合FK的重点是什么?它只会在您更新或从user_profile中删除时帮助您,但在您为用户插入新用户或新兴趣爱好时,它不会帮助您复制数据。
您要避免的联接非常便宜。只需采用第一种方法。它更易于维护,可帮助您保持数据的一致性和标准化。