MySQL 库内分库分表解读

对于轻量级数据库而言,总会有一定的瓶颈出现。硬件资源上的瓶颈,比如:IO,CPU,网络,内存等。硬件瓶颈到了一定程度是无法提升的,或无法提供更多的资源,那剩下的只能从数据库软件,设计,使用方面进行优化,达到预期目标。

当这些都无法满足的情况下,才会用到分布式数据库分库分表方式。但同比单实例投入的资源非常多的。

那么数据库内怎样进行分库分表:
(1)什么时候才需要分库分表?评判标准又是什么?

(2)按照数据增长速度,一张表存储了多少数据的时候,才需要考虑分库分表?

(3)MySQL内如何分库分表?

下面围绕着MySQL的这些问题,开始经验之旅。

数据量

从MySQL的处理能力为什么说,最高数据行只能到千万级?

按照官方给的参考值,单个表空间可以是TB级别的:

但如实际情况如何

MySQL是索引组织表,所有数据是按照B+Tree 结构构成的。B树是一种自平衡树,新增节点和删除节点后,都会按照规则进行平衡,已满足B树的规则。
如果是3层数最多进行3次磁盘I/O觉得这样在索引设计良好的情况下,或者采用覆盖索引的情况下只进行3此I/O,复杂度为log(n)并不会太影响效率。

比如:bigint是8字节,指针又占用6字节,所以指针可以指向16384 /(8+6)= 1170 个非叶子节点同理,指向叶子节点的个数也可以是1170个。

3层高的一颗B+树可以存储:
第一层指向1170个非叶子节点,第二层再指向1170个叶子节点,
     1170 * 1170 = 1368900 个叶子节点

如:一条记录1KB大小,那么一页16KB就可以存储16行, 
     16行 * 1368900 个叶子节点 = 21902400 行。

机械硬盘时代B树不要超过3层而得来的,固态硬盘时代,多几次IO一点问题都没有。目前按照接触的普遍经验单表数据行5000W~8000W内,也能达到比较好的性能。这样的数据量,实际数据文件大小在10G左右。

提问:数据量是否还可以在继续提升吗?
承载数据量当然可以继续提升,只是性能维持困难,超过1亿行之后,就会非常明显发现性能下降。这时候的瓶颈在MySQL的底层实现上。

应用瓶颈

无法提升硬件资源,满足不了业务需求,就需要数据库内分库分表。

  • 对于TPS/QPS要求比较高,有一定影响单表的处理能力
    普遍MySQL稍微高配置环境 TPS/QPS普遍都能维持在1W/10W以内指标,操过就无法满足性能要求。

  • 发现某张表的不停的访问,内存中的命中率非常低,处理能力逐步衰落,特别是并发比较大的情况下。

通过应用处理能力的延迟反馈 和 数据库指标命中率和慢日志积累结合,进行有效的判断:

#如Status值:
Innodb_buffer_pool_read_requests表示read请求的次数,
Innodb_buffer_pool_reads表示从物理磁盘中读取数据的请求次数

缓存命中率的计算方法是:
(1- Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests) *100 %,

#如慢日志:
通过历史对比慢日志记录,进行判断。数据量无明显变化,执行效率变低 等

提问:添加多个应用节点 或 缓存机制(redis), 读写分离 是否能解决?
可能缓解有一定的作用,但根原解决不了。

  • 多个应用最终还是会汇集到数据库上,压力还会上来,问题依然存在;
  • 缓存有效解决查询上的问题,但无法解决增,删,更改的业务;
  • 读写分离,因为不是实时同步,数据肯定存在一定延迟;

安全性和可用性

因设计方面考虑诸多系统类型契合,并且库表之间存在一定的耦合性,所以使用一个数据库:

  • 当处于这种情况,因为每个业务的数据量、访问量都不同,不能因为一个业务把数据库搞挂而牵连到其他业务。
  • 当一个数据库出现问题时,不会影响到其他业务,每个库只承担一部分业务,这样整体的可用性就能提高,安全也随着提高。就像比喻:“不要把鸡蛋放在一个篮子里”

提问:对于公用一个数据库实例,是否可用账号,资源方面 进行隔离?
账号隔离可以实现,但这只是表面,资源隔离才能完全解决这种情况。但资源隔离 目前MySQL无法实现。虽然MySQL8.0有这方面一些功能(资源组,连接内存限制)但不完善,还有MySQL底层还是单进程多线程,线程部分无法控制。

分库分表

那库内怎样进行有效的分库分表:

  • 分库
    随着业务推广力度加大,数据库终于成为了瓶颈,这个时候多个服务共享一个数据库基本不可行。需要将每个服务相关的表拆出来单独建立一个数据库,进行“分库”。
    单数据库能够支撑的并发量是有限,拆成多个库可以使服务间不用竞争,提升服务的性能。

  • 分表
    目前常用的有2个维度,一是水平拆分和垂直拆分,二是拆分多个表:

水平拆分和垂直拆分:
水平拆分和垂直拆分意义在于大表拆分多个小表,不需要的数据,就不需要访问原则,单表处理能力提升,加快数据库的处理能力。

  1. 垂直拆分:基于表或字段划分,表结构不同。
  2. 水平拆分:基于数据划分,表结构相同,数据不同

拆分表:
冷热数据分离,按照规律数据拆分,单表处理能力提升,加快数据库的处理能力。这是分布式数据库之前 最常用的方式,目前也普遍使用。

  1. 取模方式表:hash取模 ,range,id 为奇数偶数 或 除于某个值 获取剩余值 等方式
  2. 每日表:只存储当天的数据。
  3. 每月表:只存储当月数据。
  4. 历史表:超过一定时间的数据迁移到 history表
    正在上传…重新上传取消

总结

对于分库分表,首先得知道使用的数据库的处理能力,同时瓶颈在哪里,然后才能合理地拆分,只要能满足需求,拆分规则越简单越好。

分库分表的确解决了诸多问题,但是也给系统带来了很多复杂性:

  • 跨库关联查询
  • 聚合操作
  • 定期维护,
  • 单表数据量过大

不到万不得已不要轻易使用分库分表这个大招,避免"过度设计"和"过早优化"。分库分表之前,不要为分而分,先尽力去做力所能及的事情,例如:升级硬件、升级网络、读写分离、索引优化等等。当各方面达到瓶颈时候,再考虑分库分表。

猜你喜欢

转载自blog.csdn.net/dreamyuzhou/article/details/126776331
今日推荐