前言
现代业务越来越复杂,数据量也越来越大,关系型数据库本身就比较容易形成系统瓶颈,单机存储容量,连接数,处理能力都有限。
当单表的数据量达到一定量级以后,比如1000万,由于查询维度较多,即使添加从库,优化索引,做很多操作时性能还是下降严重。
这个时候要如何提高数据的性能呢?
有人说,可以通过提升服务器硬件能力来提高数据处理能力,比如换更快的硬盘,换更强的CPU。
这种方案成本是很高的,并且瓶颈有时候往往不在硬件上,而在数据库本身。
基于这种现状,分表/分库就出现了!
什么是分别分库
分表分库是两种操作,一种是分表,一种是分库。
但是他们的中心思想都是将数据分散,使得单一数据库/表的数据量变小来缓解单一数据库的性能问题,从而达到提升数据库性能的目的。
例如,将某业务的数据库分为若干个独立的数据库,并且对于大表也拆分为若干小表,这样就很大程度上降低了并发数据查询时的数据冲突。
分表
垂直分表
定义:将一个表按照字段分为多表,每个表里面都存储其中一部分字段。
我们以商品表来举例子:
商品信息中,一般包括多条字段,如商品名、价格、简介……
而其中商品名和价格可能是最重要的,而简介就相对没有那么重要。
对比两者:
商品名和价格:字段很小,请求很频繁。简介:字段很大,一般只有详情页才需要它。大字段都如下几个坏处:
由于数据量本身大,需要更长的读取时间跨页时,单页内的数据行越多数据库整体性能越好,而大字段占用空间大,单页内存储行数小,因此IO效率低据库以行为单位将数据加载到内存中,表中字段越短,内存能加载的数据越多,命中率更高,减少了磁盘IO,从而提升了数据库性能。因此简介这种低频数据,会拖累商品名和价格这种高频数据,这个时候,我们就可以将简介从表中拆分出来。
这样做的好处是:
查看详情的用户与商品信息浏览互不影响,避免了IO争抢并减少锁表的几率。充分发挥高频数据(商品名和价格)的操作效率,商品名和价格的操作的高效率不会被商品简介的低效率所拖累。水平分表
定义:同一个数据库内,对数据行拆分,不影响表结构。
优点:
优化单一表数据量过大而产生的性能问题。避免IO争抢而减少锁表的几率。加入Java学习交流君样:1142951706 一起吹水聊天!分库
虽然通过分表性能得到一定程度的提升,但是很多时候还无法达到预期效果。
因为数据库始终限制在一台服务器上,所以分表有如下几个局限性:
磁盘空间可能不够。只解决了单一表数据量过大的问题。每个表还是竞争同一个物理机的物理资源。垂直分库
定义:专库专用,按照业务将表进行分类,分布在不同的数据库中,每个库可以放在不同的服务器上
例如,我们可以将购物车表、商品表、店铺表、买家表分在不同的服务器中。
优点:
解决业务层面的耦合,业务清晰能对不同业务的数据进行分级管理、维护、监控、扩展等高并发场景下,垂直分库一定程度的提升IO、数据库连接数、降低单机硬件资源的瓶颈水平分库
随着业务的继续扩大,垂直分库也将在次面临单表过大的情况。
而已经经过了垂直分库,我们很难再进行进一步的垂直细分,这时候就要尝试水平分库了。
水平分库和水平分表十分相似,应该说就是水平分表是水平分库的一种延续。
定义:同一个表的数据按一定规则拆到不同的数据库中,库放在不同的服务器上。
优点:
解决了单库大数据,高并发的性能瓶颈提高了系统的稳定性及可用性分库分表的缺点
分页/排序
在同一张表时,只需要用
limit
、
order by
便可轻松搞定。
跨节点多库进行查询时,分页、排序,就变得很复杂。
先在不同的分片节点中将数据进行排序并返回然后将不同分片返回的结果集进行汇总和再次排序主键重复
分表分库会让平时经常使用的主键自增长形同虚设。生成的ID无法保证全局唯一。
因此我们需要单独设计全局主键,以便面跨库主键重复问题。
事务的一致性
因为分库分表把数据分布在不同的库、不同服务器,所以不可避免的带来分布式事务问题。
当一个请求要先请求数据库A,再请求数据库B,这两个属于同一个事务,多个库会导致分布式事务问题。
需要有一些措施来保证事务一致性的问题,这里不在展开,有兴趣自行了解。
关联查询
分库后,如果两个表不在同一个数据库,甚至不在同一台服务器上,无法进行关联查询。
解决方案:
将原关联查询分为两次查询第一个查询的结果找出关联数据id根据id发起第二次请求得到关联数据最后将获得的数据进行拼装总结
分库分表的诞生是为了解决数据库的性能瓶颈,虽然有很多好处,但相应的也有很多坏处。
但在业务量还不大的时候,我们其实应该首先考虑索引、缓存、读写分离等方案,盲目使用分表分库技术,会导致业务变得臃肿,反而徒增烦恼。