谈一谈Mysql分库分表
分库分表这个词相信很多人都不陌生,在数据到达一定规模的时候,多数都会对数据进行分库分表。
# 分表
当单张表表里面的数据太多了,如果都存在一张表里吃不消,所以这时候得分表, 从维度上来讲,分表又分垂直分表和水平分表。
# 垂直分表
垂直分表就是将一张表的列拆分成几张不同的表,比如表中有10列,分成了两张表,其中一张表3列,另一张表7列。
垂直分表适合表中存在不常用并且占用了大量空间的表拆分出去。
比如用户表只有用户id、昵称、手机号、个人简介这4个字段。但是手机号和个人简介这种信息就属于不太常用的,占用的空间也不小,所以就把手机号和个人简介这两列拆分出去。
那垂直分表影响就是之前只要一个查询的,现在需要两次查询才能拿到分表之前的完整用户信息。
# 水平分表
水平分表就是将同一张表中的数据,才拆分到同样表结构,单名字不同的表中,依次缓解单表过大的问题。假设单张表有5000万行数据,分成5个表,每个表1000万行数据。
水平分表一般有以下几种做法:
- 按范围分表
比如id 值1-999万的放一张表,1000万-1999万放一张表,依次类推。这种分法简单粗暴,以后新增的数据分表都不会影响到之前的数据,之前的数据都不需要移动。
- 按哈希值取模分表
比如拿id来做哈希,1500取余8等于4,所以这条记录就放在user_4这个表中,2011取余8等于3,所以这条记录就放在user_3中。这种分法好处就是分的很均匀,基本上每个表的数据都差不多,但是以后新增数据又得分表了咋办,以前的数据都得动。
- 新增路由关系表
还是拿用户表来说,就是弄一个路由表,里面存userId和表编号,表示这个userId是这张user表的的。这种方式也简单,之后又要分表了之后改改路由表,迁移一部分数据,但是这种方法导致每次查询都得查两次,并且如果路由表太大了,那路由表又成为瓶颈。
分表规则弄好后其实只是完成了分表的第一步,真正麻烦的是数据迁移,或者说是如何做到对业务影响最小的数据迁移,除非是一开始就做了分表,所以数据迁移这一步骤肯定是跑不掉的。
# 分库
分表完成后可以解决单表的压力,但数据库本身的压力却没有下降,数据库里“其他表”的写入依然导致整个数据库 IO 增加,可以尝试把“业务关联度”不是很高的表单独移到一个新的数据库中,完全和现有的业务隔离开来。
# 总结
以MySQL为例,B+树索引的深度会随着记录的增多而逐渐加深,根据索引查询的开销也会越来越大,而单表拆分成多个表之后,B+树深度降低,每个单表独立查询的速度也会加快,如果同时还分库的话,并且在不同的实例上,大量的查询压力也会分担到不同的机器上,这对单个数据库机器减压也带来好处。