一、什么是分库分表
一.分库
分库就是一个数据库分成多个数据库,部署到不同机器。
二.分表
就是一个数据库表分成多个表
二、为什么需要进行分库分表
一.为什么需要分库呢?
1、磁盘存储
业务量剧增,MySQL单机磁盘容量会撑爆,拆成多个数据库,磁盘使用率大大降低。
2、并发连接支持
我们知道数据库连接是有限的。在高并发的场景下,大量请求访问数据库,MySQL单机是扛不住的!当
前非常火的微服务架构出现,就是为了应对高并发。它把订单、用户、商品等不同模块,拆分成多个应
用,并且把单个数据库也拆分成多个不同功能模块的数据库(订单库、用户库、商品库),以分担读写
压力。
二.为什么需要分表
数据量太大的话,SQL的查询就会变慢。如果一个查询SQL没命中索引,千百万数据量级别的表可能会
拖垮整个数据库
即使SQL命中了索引,如果表的数据量超过一千万的话,查询也是会明显变慢的。这是因为索引一般是
B+树结构,数据千万级别的话,B+树的高度会增高,查询就变慢。
三、如何进行分库分表
一.垂直拆分
1、垂直分库
垂直分库,将原来一个单数据库的压力分担到不同的数据库,可以很好应对高并发场景
2、垂直分表
如果一个单表包含了几十列甚至上百列,管理起来很混乱,每次都 select * 的话,还占用IO资源。这时
候,我们可以将一些不常用的、数据较大或者长度较长的列拆分到另外一张表。
比如一张用户表,它包含 user_id、user_name、mobile_no、age、email、nickname、address、user_desc ,
如果 email、address、user_desc 等字段不常用,我们可以把它拆分到另外一张表,命名为用户详细信息
表。这就是垂直分表
二.水平拆分
1、水平分库
水平分库是指,将表的数据量切分到不同的数据库服务器上,每个服务器具有相同的库和表,只是表中
的数据集合不一样。它可以有效的缓解单机单库的性能瓶颈和压力。
2、水平分表
如果一个表的数据量太大,可以按照某种规则(如 hash取模、range ),把数据切分到多张表去。
一张订单表,按 时间range 拆分如下:
三.水平分库分表策略
1、range范围
range,即范围策略划分表。比如我们可以将表的主键,按照从 0~1000万 的划分为一个表, 1000~2000
万 划分到另外一个表。如下图:
优点:这种方案有利于扩容,不需要数据迁移。假设数据量增加到5千万,我们只需要水平增加一张表就
好啦,之前 0~4000万 的数据,不需要迁移。
缺点:这种方案会有热点问题,因为订单id是一直在增大的,也就是说最近一段时间都是汇聚在一张表里
面的。比如最近一个月的订单都在 1000万~2000 万之间,平时用户一般都查最近一个月的订单比较
多,请求都打到 order_1 表啦,这就导致数据热点问题。
2、hash取模
hash取模策略:指定的路由key(一般是user_id、订单id作为key)对分表总数进行取模,把数据分散
到各个表中
比如原始订单表信息,我们把它分成4张分表:
优点:hash取模的方式,不会存在明显的热点问题。
缺点:如果一开始按照hash取模分成4个表了,未来某个时候,表数据量又到瓶颈了,需要扩容,这就比较棘手了。比如你从4张表,又扩容成 8 张表,那之前 id=5 的数据是在( 5%4=1 ,即t_order_1),现在应该放到( 5%8=5 ,即t_order_5),也就是说历史数据要做迁移了。
3、range+hash取模混合
既然range存在热点数据问题,hash取模扩容迁移数据比较困难,我们可以综合两种方案一起嘛,取之
之长,弃之之短。
比较简单的做法就是,在拆分库的时候,我们可以先用range范围方案,比如订单id在0~4000万的区
间,划分为订单库1;id在4000万-8000万的数据,划分到订单库2,将来要扩容时,id在8000万~1.2亿的
数据,划分到订单库3。然后订单库内,再用hash取模的策略,把不同订单划分到不同的表。
四、什么时候才考虑分库分表
一.什么时候分表?
如果你的系统处于快速发展时期,如果每天的订单流水都新增几十万,并且,订单表的查询效率明变慢时,就需要规划分库分表了。一般B+树索引高度是2~3层最佳,如果数据量千万级别,可能高度就变4层了,数据量就会明显变慢了。不过业界流传,一般500万数据就要考虑分表了。
二.什么时候分表?
如果业务量继续增大,多个服务共享一个单体数据库,数据库就成了性能瓶颈,就需要考虑分库。比如订单、用户等,都可以抽取出来,新搞个应用(其实就是微服务思想),并且拆分数据库(订单库、用户库)。
数据库被切分后,不能再依赖数据库自身的主键生成机制,最简单可以考虑UUID(不连续,性能不佳),或者使用雪花算法生成分布式ID(推荐使用)。