搞懂数据库-关系型数据库设计
背景
面对海量数据,例如,上千万甚至上亿的数据,查询一次所花费的时间会变长,甚至会造成数据库的单点压力。那么数据库应该怎么来设计才更合理呢?
对于一个复杂多变的场景,数据库应该怎么来设计?
1.分库和分表设计
1.分表
1.1为什么要分表
分库与分表的目的在于,减小数据库的单库单表负担,提高查询性能,缩短查询时间,此外,可以很大的缓解表锁的问题
1.2什么时候分表
那么什么时候应该分库和分表呢,阿里巴巴《Java 开发手册》提出单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。
1.3怎么分表
分表策略可以归纳为垂直拆分和水平拆分
1.3.1垂直拆分
把表的字段进行拆分,即一张字段比较多的表拆分为多张表,这样使得行数据变小。举个例子,假设用户表中有一个字段是家庭地址,这个字段是可选字段,在数据库操作的时候除了个人信息外,并不需要经常读取或是更改这个字段的值。在这种情况下,更建议把它拆分到另外一个表,从而提高性能。
建议:
- 将不常用的字段单独拆分到另外一张扩展表
- 将大文本的字段单独拆分到另外一张扩展表
- 将不经常修改的字段放在同一张表中,将经常改变的字段放在另一张表中
- 对于需要经常关联查询的字段,建议放在同一张表中
1.3.2水平拆分
把表的行进行拆分。因为表的行数超过几百万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。水平拆分,有许多策略,例如,取模分表,时间维度分表,以及自定义 Hash 分表。例如用户 ID 维度分表等。在不同策略分表情况下,根据各自的策略写入与读取。常见的水平分表策略归纳起来,可以总结为随机分表和连续分表两种情况。例如,取模分表就属于随机分表,而时间维度分表则属于连续分表。
区别
- 连续分表有可能存在数据热点的问题,有些表可能会被频繁地查询从而造成较大压力,热数据的表就成为了整个库的瓶颈,而有些表可能存的是历史数据,很少需要被查询到。
- 随机分表的数据相对比较均匀,不容易出现热点和并发访问的瓶颈
建议
- 对于日志场景,可以考虑根据时间维度分表
- 对于海量用户场景,可以考虑取模分表,数据相对比较均匀,不容易出现热点和并发访问的瓶颈。
2.分库
2.1为什么要进行分库
库内分表解决了单表数据过大的问题,但是没有把单个表的数据分配到不同的物理机上,因此并不能减轻Mysql服务器的压力。
2.2怎么分库
2.2.1垂直分库
按照业务和功能划分,把数据分别放到不同的数据库中,例如老师的数据放一个数据库,学生的数据放一个数据库,
2.2.2水平分库
把一张表的数据划分到不同的数据库,两个数据库的表结构一样。实际上,水平分库与水平分表类似,水平拆分有许多策略,例如,取模分库,自定义 Hash 分库等,在不同策略分库情况下,根据各自的策略写入与读取。举个例子,随着业务的增长,资讯库的单表数据过大,此时采取水平拆分策略,根据取模分库。
注:仅用于学习交流