时间:2021-07-01 10:21:17 帮助过:15人阅读
表字段外,怎样对表进行分割以及划分是范式主要讨论的问题
由于五范式的有用性太低,仅仅考虑三大范式
来一张学生选课表
Student_Course(studentId, studentName, collegeId, collegeName, courseId, courseName, credit)
上面假设一个学生选了多门课,我们有例如以下的办法: courseName中用,号分割。
这显然不能满足第一范式了。
我们还有个办法就是使用(studentId, courseId)来作为这个联合主键。这样就会有非常多反复行了。
这个也是经典的多对多关系引起的问题。
能够觉得是拆分一个多对多为两个1对多
上面的数据studentName 部分依赖于(studentId, courseId)
会引入例如以下的问题:
传递依赖跟部分依赖非常easy混淆。会跟本表适用于做什么的有非常大的关系
这部分的主要目的是进一步去除反复数据,提出1对多
比方上面的学生课程表。 其主码显然是studentId和courseId。 这样非常easy推断出部分依赖
在第二范式分解之后的student表中, 学生信息的主键应该是studentId,另外除他以外有一个不能作为主键,可是却有可能是另外字段所以来的码为的字段:collegeId。这样StudentId->collegeId->collegeName。这就是传递依赖。
进一步分割之后:
Student(studentId, studentName, collegeId)
Collegue(collegeId, collegeName)
范式的优缺点:
- 降低反复
- 更快的更新
- 更少的须要group by等语句
- 缺点:查询时会涉及很多其它的关联
反范式优缺点:
- 缺点:冗余行及有可能更新错误
- 不须要关联
一些取舍
有时是须要混用范式和反范式的。 特别在一些须要额外的字段进行索引,统计及排序的情况下。
这样可能会带来更新上的麻烦。须要依据实际情况详细权衡。
这种情况分表的技术中也可能会用到
CREATE TABLE counter(
cnt int unsigned not null DEFAULT 0
) ENGINE = InnoDB;
假设是插入的时候每次递增1。这样就会每次都会对这一行进行排他锁。比較好的解决方案:
CREATE TABLE counter(
slot tinyint unsigned not null primary key,
cnt int unsigned not null DEFAULT 0
) ENGINE = InnoDB;
UPDATE hit_counter SET cnt = cnt + 1 where slot = FLOOR(RAND() * 100);
然后插入100行默认的数据
然后更新的时候就能够尽量少的避免并发锁行
就能够使用SUM字段算出总的点击量
假设须要每天都计算的话,那么可能的表结构为:
CREATE TABLE counter(
day date not null;
slot tinyint unsigned not null,
cnt int unsigned not null DEFAULT 0,
primary key(day, slot)
) ENGINE = InnoDB;
INSERT INTO counter VALUES(CURRENT_DATE, FLOAT(RAND() * 100), 1) ON DUPLICATE KEY UPDATE cnt = cnt + 1;
ON DUPLICATE KEY,假设出现了反复的key则更新则不是新增。
##加快DDL
DDL会堵塞服务。因此应该越快越好。
一般的方式有该备库切库。
又一次创建一个表,该表之后重名民
能够通过物化视图facebook的工具来动态的改动
Mysql第四天 数据库设计
标签: