目录
水平分表 :
数据表行的拆分,通俗点就是把数据按照某些规则拆分成多张表或者多个库来存放。分为库内分表和分库。
比如一个表有400万数据,查询很慢,可以分到四个表,每个表有400万数据
垂直分表:
列的拆分,根据表之间的相关性进行拆分。常见的就是一个表把不常用的字段和常用的字段就行拆分,然后利用主键关联。或者一个数据库里面有订单表和用户表,数据量都很大,进行垂直拆分,用户库存用户表的数据,订单库存订单表的数据。
分库分表方案:
1.取模方案:
拆分之前,先预估一下数据量。比如用户表有400w数据,现在要把这些数据分到4个表user1 user2 uesr3 user4。
比如id = 17,17对4取模为1,加上 ,所以这条数据存到user2表。
$_GET['id'] = 17, 17%4 + 1 = 2, $tableName = 'users'.'2' Select * from users2 where id = 17;
注意:进行水平拆分后的表要去掉auto_increment自增长。这时候的id可以用一个id 自增长临时表获得,或者使用 redis incr的方法。
优点是数据均匀的分到各个表中,没有热点问题。
缺点是以后的数据扩容迁移很难,比如数据量变大之后,以前分到4个表现在要分到8个表,所以取模的值就变了,就需要重新数据迁移。
2.range 范围方案
以范围进行拆分数据,这个方案比较简单,就是一定范围内的订单,存放到一个表中。比如id=12存放到user1表,id=1300万的存放到user2 表。
优点是有利于将来数据的扩容
缺点是可能热点数据都存在一个表中,而其他表没有压力。
总结:
hash取模方案:没有热点问题,但是以后数据扩容麻烦。
range范围方案:以后数据扩容迁移方便,但是有热点问题,热点数据容易都在一个表中。
如果把两者方案结合一下呢?
3.hash取模和range方案结合
如图:
group 组存放id 为0~4000万的数据,然后有三个数据库 DB0 DB1 DB2,DB0里面有四个数据库,DB1 和DB2 有三个数据库
假如id为15000 然后对10取模(为啥对10 取模 因为有10个表),取0 然后 落在DB_0,然后在根据range 范围,落在Table_0 里面。