🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 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 雪花算法。