# MySQL 中的分库分表
## <blockquote class="danger"><p>分库和分表解决了什么问题?</p></blockquote>
### 把以前存在一个数据库实例里的数据拆分成多个数据库实例,部署在不同的服务器中,这是分库。
### 分库是为了解决服务器资源受单机限制,顶不住高并发访问的问题,把请求分配到多台服务器上,降低服务器压力。
### 把以前存在一张表里面的数据拆分成多张表,这是分表。
### 分表是为了解决由于单张表数据量多大,而导致查询慢的问题。
## <blockquote class="danger"><p>一般怎么分库?</p></blockquote>
### 一般分库都是按照业务划分的,比如订单库、用户库。
## <blockquote class="danger"><p>分库会带来哪些问题?</p></blockquote>
1. 事务问题
关系型数据库,有很大一点在于它保证事务完整性,分库之后单机事务就用不上了,必须使用分布式事务来解决。
1. 连表JOIN 查询问题
在一个库中的时候我们还可以利用 JOIN 来连表查询,而跨库了之后就无法使用 JOIN 了。
## 解决办法:
1. 就是在业务代码中进行关联,也就是先把一个表的数据查出来,然后通过得到的结果再去查另一张表,然后利用代码来关联得到最终的结果。
2. 适当的冗余一些字段,避免JOIN操作
## <blockquote class="danger"><p>一般怎么分表</p></blockquote>
1. 垂直分表
![](https://img.kancloud.cn/45/0e/450e2e18ec83063c044aacf67b203aa4_481x519.png)
垂直分表的原理比较简单,一般就是把某几列拆成一个新表,这样单行数据就会变小,B+树里的单个数据页(固定16kb)内能放入的行数就会变多,从而使单表能放入更多的数据。这样内存存放更多有用的数据,就减少了磁盘的访问次数,性能就得到提升。
2. 水平分表
![](https://img.kancloud.cn/75/fe/75fe0d056017fac906b301dc1ed55ce3_761x450.png)
分表算法可以分为:Hash 路由,范围路由,路由表
* Hash 路由
其实就是选择表中的某一列,然后进行 Hash 运算,将 Hash 运算得到的结果再对子表数进行取模,这样就能均匀的将数据分到不同的子表上。
* 优点是:
数据分布均匀
* 缺点是:
就是增加子表的时候麻烦,得重新映射数据
* 范围路由
其实很简单,可以是时间,也可以是地址,表示一定的范围的即可。
比如本来一张 User 表,我可以分 User\_HZ、User\_BJ、User\_SH,按照地名来划分 User。
比如 log 表,我可以将表分为 log\_202103、 log\_202104,把日志按照年月来划分。
* 路由表
是专门搞个表来记录路由信息,一般不怎么用。
## <blockquote class="danger"><p>分表会带来哪些问题?</p></blockquote>
垂直分表还好,就是查询数据需要关联一下。
水平分表会带来很多问题:
* 排序、count、分页问题
如果一个用户的数据被拆分到多个表中,那查询结果分页就不像以前单张表那样直接就能查出来了,像 count 操作也是一样的。
* 全局主键的问题
以前单表的时候很简单,就是主键自增,现在分表了之后就有点尴尬了,所以需要一些手段来保证全局主键唯一。
1. 还是自增,只不过自增步长设置一下。比如现在有三张表,步长设置为3,三张表 ID 初始值分别是1、2、3。 这样第一张表的 ID 增长是 1、4、7。第二张表是2、5、8。第三张表是3、6、9,这样就不会重复了。
2. UUID,这种最简单,但是不连续的主键插入会导致严重的页分裂,性能比较差。
3. 分布式 ID,比较出名的就是 Twitter 开源的 sonwflake 雪花算法。