不知你有没有面试遇到过,或者工作中遇到过,水平拆分和垂直拆分的题目或需求,其实所有的东西经过思考你就会清楚的,都是不难的,我们先来说一下垂直拆分
垂直拆分
什么叫垂直拆分?为何垂直拆分?
当一个表复杂,难以维护,数据量太大,肯定会想到拆分的啦,比如:
一个数据库里面既存在用户数据,又存在订单数据,那么垂直拆分可以把用户数据放入到用户库,把订单数据放到订单库。垂直分表是对数据表进行垂直拆分的一种方式,常见是把一个多字段的大表按常用字段和非常用字段进行拆分,每个表里面的数据记录数一般情况下是相同的,只是字段不一样,使用主键关联
如果你大部分使用的字段只有username 和 email 后面的字段就形成了冗余,垂直拆分就是按照业务进行拆分,根据自己的业务场景进行垂直拆分,上表拆分后的样子
拆分原则:
1、把不常用的字段单独放到一个表中。
2、把text,blob等大字段拆分出来放在附表中。
3、经常组合查询的列放在一张表中
拆分优点:
1、可以使得数据变小,一个数据块(block)就能存放更多的数据,在查询时就会减少I/O次数(每次查询时读取的Block就少)
2、可以达到最大化利用Cache的目的,具体在垂直拆分的时候可以将不常变的字段放一起,将经常改变的放一起
3、数据维护简单
拆分缺点:
1、主键出现冗余
2、会引起表连接JOIN操作(增加CPU开销)
3、依然存在单表数据量过大的问题(需要水平拆分)
4、事务处理复杂
不常用的字段就是放在一张附表也没关系通过Join链接一下就好了。没有最好的设计,只有最合适的设计
水平拆分
水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。
水平拆分是通过某种策略将数据分片来存储,分库内分表和分库两部分,每片数据会分散到不同的MySQL表或库,达到分布式的效果,能够支持非常大的数据量。前面的表分区本质上也是一种特殊的库内分表
库内分表,仅仅是单纯的解决了单一表数据过大的问题,由于没有把表的数据分布到不同的机器上,因此对于减轻MySQL服务器的压力来说,并没有太大的作用,大家还是竞争同一个物理机上的IO、CPU、网络,这个就要通过分库来解决
拆分原则
1、取模的方式,如:分四张表,Id%4+1 如果值为1就存表1,2存为表2
2、如:订单号最后一位是0,1,2,3,4,5,6,7,8,9等来确定存放具体的表如表1,表2...........
3、也可通过根据订单号根据自己设定的算法,进行把订单号和存放的表位置放到redis中,根据redis来读取
实际情况中往往会是垂直拆分和水平拆分的结合,即将Users_A_M和Users_N_Z再拆成Users和UserExtras,这样一共四张表。
水平拆分优点:
1、不存在单库大数据和高并发的性能瓶颈
2、应用端改造较少
3、提高系统稳定性和负载能力。
水平拆分缺点:
1、分片事务一致性难以解决
2、复杂逻辑,跨节点Join性能会差
3、数据维护难度增加
总之遇到数据表太大瓶颈,水平拆分解决方案是不错的,具体看自己的情况,优点大于缺点,上面缺点很多都可以解决