不要为了“分库分表”而“分库分表”

6,184 阅读9分钟

为什么要进行分库分表?

当数据库的数据量过大,大到一定的程度,我们就可以进行分库分表。那么基于什么原则,什么方法进行拆分,这就是本篇所要讲的。

为什么要进行分库分表?当数据库大到一定程度的时候,我们采用优化硬件,优化表的结构,这种方法还是无法满足的时候,就要进行分库分表。

分库分表是什么?

随着公司的业务快速发展,数据库中的数据量猛增,访问性能也变慢了,优化迫在眉睫。

分析下问题出现哪里呢?关系型数据本身就比较容易形成系统瓶颈,单机存储容量,连接数,处理能力都有限。当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库,优化索引,做很多操作时性能还是下降严重。

方法一:

通过提升服务器硬件能力来提高数据处理能力,比如增加存储容量,CPU等,这种方案成本很高,并且如果瓶颈在MySQL本身,那么提高硬件也是很有限的。


方法二:

将数据分散在不同的数据库中,使得单一数据库的数据量变小来缓解单一数据库的性能问题,从而达到提升数据库性能的目的。

比如,将电商的数据库分为若干个独立的数据库,并且对于大表也拆分为若干小表,从而解决数据库的性能问题。就跟把鸡蛋放在多个篮子里是一样的。



所以,分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题,将原来独立的数据库拆分为若干数据库,将数据库大表拆分成若干数据表,使得单一数据库,单一数据表的数据量变小,从而达到提升数据库性能的目的。

分库分表的方式

我们将电商作为其背景,现在有三个表,分别是卖家表,商品表,店铺表。

垂直分表

我们平时逛淘宝等电商网站时,搜索列表的页面显示商品的关键信息,而点进去的页面显示商品的详情信息。这个商品信息大表所包含的字段有很多,所以我们将商品信息中常用的字段归为一个表,商品信息中不常用的字段归为一个表。

垂直分表的定义:将一个表按照字段分为多表,每个表里面都存储其中一部分字段。

他带来的提升是:

1.为了避免IO争抢并减少锁表的几率,查看详情的用户与商品信息浏览互不影响。

2.充分发挥热门数据(商品的基础信息)的操作效率,商品信息的操作的高效率不会被商品描述的低效率所拖累。

为什么大字段效率低,比如商品表的描述信息?:第一是由于数据量本身大,需要更长的读取时间;第二是跨页,页是数据库存储单位,很多查找及定位操作都是以页为单位,单页内的数据行越多数据库整体性能越好,而大字段占用空间大,单页内存储行数小,因此IO效率低;第三,数据库以行为单位将数据加载到内存中,这样表中字段较短且访问评率交到,内存能加载更多的数据,命中率更高,减少了磁盘IO,从而提升了数据库性能。

一般来说,当表的数据量很大时,可以将表按字段切开,将热门字段和冷门字段分开,放在不同的表中,避免发生IO争抢。

垂直分库

通过垂直分表性能得到一定程度的提升,但是还没有达到要求,并且磁盘空间已经不够了,因为数据库始终限制在一台服务器上,库内的垂直分表只解决了单一表数据量过大的问题,单没有将表分布到不同的服务器上,因此每个表还是竞争同一个物理机的CPU,内存,网络IO,磁盘等物理资源。

所以,我们可以将卖家表,商品表,店铺表分在不同的服务器中。

垂直分库是指按照业务将表进行分类,分布在不同的数据库中,每个库可以放在不同的服务器上,他的核心就是专库专用。

水平分库

经过垂直分库,数据库性能问题得到一定程度的解决,但是随着业务量的增长,商品单裤存储数据已经超出预估。粗略估计,目前有8w店铺,每个店铺平均150个不同规格的商品,再算上增长,那商品数量得往1500w上预估,而且商品库属于访问非常频繁的资源,单台服务器已经无法支撑。此时,该如何优化。

尝试水平分库,将店铺ID为单数和店铺ID为双数的商品信息分表放在两个库中。

水平分库是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。

他带来的提升是:

解决了单库大数据,高并发的性能瓶颈。

提高了系统的稳定性及可用性。(稳定性体现在IO冲突减少,锁定减少,可用性指某个库出问题,部分可用)

水平分表

水平分表是在同一个数据库内,把同一个表的数据按一定的规则拆到多个表中。(对数据行拆分,不影响表结构)

他带来的提升

优化单一表数据量过大而产生的性能问题。

避免IO争抢而减少锁表的几率。

小结:

本小结介绍了分库分表的各种方式,他们分别是垂直分表,垂直分库,水平分库和水平分表。

垂直分表:可以吧一个宽表的字段按访问频次,是否是大字段的原则拆分为多个表,这样既能使业务清晰,还能提升部分性能,拆分后,尽量从业务角度避免联查,否则性能方面将得不偿失。

垂直分库:可以把多个表按业务耦合松紧归类,分别存放在不同的库,这些库可以分布在不同服务器,从而使访问压力被多服务器负载,大大提升性能,同事能提高整体架构的业务清晰度,不同的业务可根据自身情况定制优化方案,但是他需要解决跨库带来的所有复杂问题。

水平分库:可以把一个表的数据(按数据行)分到多个不同的库,每个库只有这个表的部分数据,这些库可以分布在不同的服务器上,从而使访问压力被多服务器负载,大大提升性能,他不仅需要解决跨库带来的所有复杂问题,还要解决数据路由的问题(数据路由问题后边介绍)。

水平分表:可以把一个表的数据(按数据行)分到同一个数据库的多张表中,每个表只有这个表的部分数据,这样做能小幅提升性能,他仅仅作为水平分库的一个补充优化。

一般来说,在系统设计阶段就应该根据业务耦合松紧来确定垂直分库,垂直分表方案,在数据量及访问压力不是特别大的情况下,首先考虑缓存,读写分离,索引技术等方案,若数据量极大,且持续增长,再考虑水平分库水平分表方案。

分库分表带来的问题

分库分表能有效的缓解了单机和单库带来的性能瓶颈和压力,突破网络IO,硬件资源,连接数的瓶颈,同时也带来了一些问题。

事务一致性问题

由于分库分表把数据分布在不同的库甚至不同服务器,不可避免的带来分布式事务问题。

比如一个请求要先请求数据库A,再请求数据库B,这两个属于同一个事务,多个库会导致分布式事务问题。

跨节点关联查询

在没有分库前,我们可以很简单的进行两表的关联查询,但是分库后,如果两个表不在同一个数据库,甚至不在同一台服务器上,无法进行关联查询。

可以将原关联查询分为两次查询,第一个查询的结果找出关联数据id,然后根据id发起第二次请求得到关联数据,最后将获得的数据进行拼装。

跨节点分页,排序函数

跨节点多库进行查询时,limit分页,order by排序问题,就变得比较复杂,需要先在不同的分片节点中将数据进行排序并返回,然后将不同分片返回的结果集进行汇总和再次排序。

主键避重

在分库分表环境中,由于表中数据同时存在不同数据库中,主键值平时使用的自增长将无用武之地,某个库生成的ID无法保证全局唯一。因此需要单独设计全局主键,以便面跨库主键重复问题。

公共表

实际应用场景中,参数表,数据字典表等都是数据量较小,变动少,而且属于高频联合查询的依赖表,但是其又没有必要分库分表,比如地理区域表也属于此类型。

可以将这类表在每个数据库都保存一份,所有对公共表的更新操作都同时发送到搜的分库执行。

结语(重点)

如标题所示,我们不能为了分库分表而分库分表,首先我们需要知道分库分表的诞生是因为数据库的性能瓶颈导致的,也就是如果没有性能瓶颈,没必要使用分库分表,毕竟技术是为了更好的服务于性能。其次,分库分表也带来了其他的问题,没必要时系统变得臃肿,不便。

即,一切以业务为准,不能盲目追求技术的新颖,牛逼。

最后

关注偶哦,领取超多学习资料。