Mysql(三)建表分表
建表分表
1、三大范式
(1)第一范式(1NF)
- 第一范式要求数据库表的每一列具有原子性,都是不可分割的基本数据项,同一列中不能有多个值。
- 若某一列有多个值,可以将该列单独拆分成一个实体,新实体和原实体间是一对多的关系。
- 在任何一个关系数据库中,第一范式是对关系模式的基本要求,不满足第一范式的数据库就不是关系数据库。
(2)第二范式(2NF)
- 满足第二范式必须先满足第一范式。
- 非主属性必须完全依赖于主键。
完全依赖:实体中每一行的所有非主属性都必须完全依赖于主键且当主键由多个属性构成时,不允许存在非主属性依赖于主键中的某一部分属性。
若存在哪个非主属性依赖于主键中的一部分属性,那么要将发生部分依赖的这一组属性单独新建一个实体,并且在旧实体中用外键?与新实体关联,并且新实体与旧实体间是一对多的关系。
(3)第三范式(3NF)
- 满足第三范式必须先满足第二范式。
- 属性不依赖于其他非主属性,实体中的属性不能是其他实体中的非主属性,不能出现冗余。
- 如果一个实体中出现其他实体的非主属性,可以将这两个实体用外键?关联,而不是将另一张表的非主属性直接写在当前表中。
2、分表
在互联网公司或者一些并发量比较大的项目,单一数据库肯定是不行的,为了解决这个问题,就可以使用分库分表
分库分表的方式:
(1)把一个实例的多个数据库拆分到不同的实例,这个实例可能是数据库集群(拆成多mysql)
优缺点:
操作简单
但是如果写压力存在某个库,这样拆分还是无法解决问题
(2)把一个库中的表拆分到不同的数据库(拆成多库)
例如:把一个库中的订单表、商品表、购物车表分别拆分到不同的数据库
(3)水平拆分(拆成多表)
在前面两种情况无法解决的情况下,就要使用水平拆分
对一个库中的相关表进行水平拆分到不同实例的数据库,进行分片处理
分片处理是最后的方案,能在之前解决问题,就不要分片,分片之后会带来很多问题,也会变得复杂
分片前的准备:
a.分区键决定了分区后的性能,如何选择分区键:
1、分区键要能尽量避免跨分片查询的发生
2、分区键要尽可能使各个分片中的数据平均
b.如何存储不需要分片的表:
1、每个分片存储一份相同的数据,数据量不大且很少更新的表
2、使用额外的节点同一存储
c.如何在节点上部署分片:
每个分片使用单一数据库,且数据库名相同
将多个分片表存储在一个数据库中,在表名后加上分片号后缀
在一个节点中部署多个数据库,每个数据库包含一个分片
d.如何分配分片中的数据:
按照分区键的Hash值取模来获取分片数据
按照分区键的范围来分配分片数据,一般日期类型可以使用这种
使用分区键和分片的映射表来分配分片数据
e,如何生成全局ID:
使用auto_increment_increment(和分片数量一致)和auto_increment_offset参数,只适用于一个节点保存一个分片的场景
使用全局节点生成ID,先获取全局节点ID,再通过分区函数插入到对应的分片中,但是这个全局节点可能成为性能瓶颈
在Redis中创建全局ID,最优选择
可以通过工具OneProxy来进行数据库分片,本来想要手动操作的,但是发现oneProxy官网没了。。。