码迷,mamicode.com
首页 > 其他好文 > 详细

要不要冗余字段

时间:2016-05-06 21:54:01      阅读:484      评论:0      收藏:0      [点我收藏+]

标签:

这个问题我也遇到了,百度到这里却发现没有答案。
这个问题我纠结了老长时间,至今仍未想明白。
但是与其万马齐喑不如胡说八道。
如果用户表添加计数字段,好处在于用空间换时间,查询速度肯定快多了;如果追求简洁无冗余,好处在于清晰易懂,写代码不蔓不枝,特别漂亮。
如果用户表添加计数字段,坏处在于难以维护。当你添加一个粉丝关系的时候需要更新关注数和粉丝数,当你删除一个粉丝关系的时候也需要更新关注数和粉丝数。当你删除一个用户的时候,与他相关的所有粉丝关系、关注关系都要删除,相对应的粉丝数关注数也要删除,这个动作怎么完成呢?通过java代码,那就要把全部信息读到内存中去,逻辑挺复杂,先删除谁,后删除谁,如果有好几层(用户-话题-帖子-评论)那就不好整了。如果通过触发器+级联删除的方式,触发器好理解,在插入删除时update一下就可以了。如果用到级联删除,那就必然用到外键,在创建外键的时候添加一句on delete cascade,一旦级联删除,那么触发器语句就失灵了,比如,你删除了话题,话题下的帖子被级联删除了,用户的帖子数却不会发生变化,因为级联删除的东西不会触动触发器!于是我说,那我就单单用触发器,不再使用外键+级联删除了,因为触发器完全可以实现级联删除的功能,只不过写的删除时触发语句比较长罢了。可是,也不行。因为触发器和函数禁止循环调用,比如我删除了话题,触发删除相关帖子,删除相关帖子时,就会触发更新话题的帖子数,这就形成了一个循环,运行时报错!运行时报错!写在触发器语句中的东西编译不报错运行时报错。
如果不设计冗余字段,也慢不了多少,建立完外键或者索引之后查询速度会提升很多。如果觉得这么整写sql语句会变长不如冗余字段好看,那也简单,建立视图呀,看上去跟冗余字段差不多,但它的内心却是十分纯洁不像冗余字段繁琐难维护。
如果冗余字段可控容易维护,那么维护它;如果冗余字段不可控,那么冗余的毫无价值,删除掉追求简洁。
存在未必合理,合理的是永远存在的。别说:人家既然设计了这个功能,那肯定有人家的道理。
没道理,存在未必合理。要用自己的眼光去看清用自己的大脑去分析。
结末的结论便是:用视图+查询语句+外键cascade级联删除来替代冗余字段。
一个小样例来测试级联删除与触发器(基于mysql):
只有三个表:用户,话题,帖子。创建完后,插入一个用户,一个话题,一个帖子。此时发现用户的话题数,帖子数都变成了1。
然后删除话题,发现用户的话题数变为0,帖子数却不发生变化,这表明话题级联删除了帖子,却没有触发帖子的删除事件。
drop database if exists test;
create database test;
use test;
drop table if exists user;
CREATE TABLE user (
    id INT AUTO_INCREMENT PRIMARY KEY,
    postCount INT,
    topicCount INT
);

drop table if exists topic;
CREATE TABLE topic (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(10),
    userId INT,
    postCount int ,
    foreign key(userId)references user(id) on delete cascade
);

drop table if exists post;
CREATE TABLE post (
    id INT AUTO_INCREMENT PRIMARY KEY,
    content VARCHAR(10),
    topicId INT,
    userId int ,
    foreign key(topicId)references topic(id) on delete cascade,
    foreign key(userId)references user(id) on delete cascade
);

delimiter ;;
create trigger ai_topic after insert on topic  for each row
begin
    update user set topicCount=topicCount+1 where user.id=new.userId;
end;;
create trigger ad_topic after delete on topic for each row 
begin
    update user set topicCOunt=topicCount-1 where user.id=old.userId;
    delete from post where topicId=old.id;
end;;
create trigger ai_post after insert on post for each row
begin
    update user set postCOunt=postCount+1 where user.id=new.userId;
    update topic set postCount=postCOunt+1 where topic.id=new.topicId;
end;;
create trigger ad_post after delete on post for each row 
begin
    update user set postCount=postCount-1 where user.id=old.userId;
    update topic set postCOunt=postCOunt-1 where topic.id=old.topicId;
end;;
delimiter ;

 

 

要不要冗余字段

标签:

原文地址:http://www.cnblogs.com/weidiao/p/5466993.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!