2. 插入异常:联盟新增了新球员,但是还在休赛期,比赛相关的字段就插入异常。就是候选键部分字段以及他们决定的非主属性
有数据,但是候选键其他部分的字段以及其他非主属性还未产生数据时,就插入异常。
3. 删除异常:如果有一场比赛只有一个球员参与,这个球员这个赛季退役了,删除这个球员的时候同时也删除了这场比赛了。
4. 更新异常:当一个球员的年龄变化了,需要更新这个球员参加的所有比赛的行。
5. 总的来说,第1个问题导致了后面3个问题,因为数据冗余,导致数据的增删改查都不对劲。
为满足2NF改正:
将这张表分为3张表
player:球员编号,姓名,年龄,队伍
game:比赛编号,比赛时间,比赛场地
player_game:比赛编号,参赛球员编号,参赛球员得分
将刚才不满足2NF的关系拆分成不同的表,并且使用第3张表进行链接他们。这样每一张表都满足2NF。
3NF在满足2NF的同时,对任何非主属性都不传递依赖于候选键
举个例子,现在有个cdn_load的表,其中有自增主键id,时间戳event_timestamp,资源类型cdn_type,加载该资源的页面名称
page_name,是不是游戏平台的域名is_game_platform,域名还是具体的链接url_type。
候选键有:(id)和(event_timestamp, cdn_type, page_name, url)
选择id作为主键时
有以上依赖关系
左边这个关系中,主键id可以决定event_timestamp,url,is_game_platform,但是这里有一个非主属性决定了另一个非主属性,url
可以决定is_game_platform,所以is_game_platform通过url传递依赖主键id。
同样右边的关系中,url_type通过url传递依赖主键id。
其实is_game_platform和url_type可以不存入DB,删除is_game_platform和url_type,直接通过程序计算所得即可,这样就满足了
3NF。
如果一定要这两个字段并且一定要满足3NF,那么拆分成两张表
cdn_request:除去is_game_platform和url_type的其他字段。
url_info:url,is_game_platform,url_type
这样两张表都满足3NF。
反范式设计
尽管围绕着数据表的设计有很多范式,但事实上我们在设计数据表的时候却不一定要参照这些标准。
我们知道越高阶的范式,数据冗余越低,但是有时候,我们在设计数据表的时候,还需要为了性能和读取效率违反范式原则。换句话
说,就是允许少量的冗余,通过空间换时间。
比如博客评论这个场景
假设设计有以下两张表:
comment:comment_id/blog_id/comment_text/time/user_id
user_id:user_id/user_name/create_time
因为在评论表中,我们不会只展示用户id,会展示用户的名称,所以查询评论列表的时候,需要连表查询,增加耗时。
评论