谈谈为什么要分库分表?

· 浏览次数 : 0

小编点评

**分库分表的优势:** * 降低单数据库服务的压力,增加系统可用性。 * 提升数据库读写性能。 * 降低表的数据规模,提高查询效率。 **分库分表的可能问题:** * 事务问题:分库可能导致一次事务的执行的数据不在同一个服务器上,数据库层面无法实现所有服务的事务操作。 * 主键唯一性问题:分库时,主键可能会发生冲突。 * 跨库多表join问题:分库后,数据可能分布在不同的服务器上,这种跨节点的 join 会有很多问题。 * 跨库聚合查询问题:跨库进行聚合查询时,如 group by,order by 等,会变的异常复杂,导致常需要复杂的业务代码才能实现上述业务逻辑。

正文

前言

由于数据库的承载能力是有限的,当业务增长量达到一定规模后,数据库的性能就会达到瓶颈。于是产生了分库分表的解决方案,本文将详细讲解什么是分库分表,以及分库分表的原因和可能产生的问题。


一、为什么要分库分表?

1. 分库的原因

数据库的关键性能指标主要有磁盘空间、内存、CPU。在数据库配置无法升级的情况下,当数据量过大可能产生如下的一些问题:

  1. 磁盘空间不足,数据库将无法进行增删改等操作;
  2. CPU 或内存不足,则可能导致读写性能低产生慢 SQL,进而导致数据库链接池被打满、内存溢出等问题。

这时就需要进行分库操作,来保证数据库的稳定和性能。

2. 分表的原因

由于数据库的承载能力是有限的,当业务增长量达到一定规模后,数据库的性能就会达到瓶颈。就拿使用最多的 MySQL 来进行说明。

MySQL 的默认引擎是 InnoDB,数据是存在聚簇索引中,而聚簇索引的底层数据结构是 B+ Tree,即使 B+Tree 已经在 B Tree 的基础上优化了空间利用率,但是随着数据规模的增大,树的高度也会达到一定规模,高度能够决定磁盘IO的次数,磁盘IO次数越多,对于性能就会越低。

image.png

3. 微服务架构

现在大部分公司的系统架构都已是分布式系统和微服务架构,根据公司的业务划分,分解为功能单一的数据库。此时会需要进行分库分表操作。

二、数据量多大才需要分库分表?

如下图,根据阿里开发手册中描述,单表超 500 万行,或容量超 2GB 时推荐分库分表。但是具体的情况还是需要根据业务需求、数据库硬件配置、CPU 性能等方面综合评估。

除此之外,要想详细的估算出数据量的瓶颈,还需要根据表的结构以及索引情况,表的字段不同的类型占用的大小也不同,故每条数据占用的大小也不同, B+Tree 每一层的存储数据量的大小也会发生变化。

综上,数据量多大需要根据自身情况去评估,并不一定是网上所说的 1000 万,也不一定是阿里所说的大于 500 万,这就是有些企业单表数据即使超过几千万仍可稳定运行的原因。

image.png

三、什么是分库分表?

1. 分库

将数据库中的表按照某种规则拆分到多个数据库中,来保证系统的稳定和性能。

如图,将 DataBase 中的 2 张表拆分成 trade 库和 acount 库,分别存 order 表和 acount 表。

image.png

2. 分表

将表中数据按照某种规则拆分到多张表中,提升查询效率。

如图,将 order 表拆分成 order_shanghai 和 order_beijing,分别存上海和北京的订单数据。

image.png

四、如何分库分表?

分库分表的核心就是数据切分(Sharding),以及切分后对数据的快速定位与结果整合,从而到提升数据库操作性能的目的。分库分表可以从垂直和水平两种纬度进行拆分。

1. 垂直拆分

垂直拆分包含垂直分库和垂直分表。

1.1 垂直分库

垂直分库指的是,将某个库中的表拆分到多个库,每个库包含的表不一样。一般主要是按照业务维度进行拆分,不同的业务数据放到对应的数据库中,核心理念是转库专用,这也是微服务拆分的一个重要依据。

如图,在电商系统中,主要包含的业务有商品、用户、支付、库存等,在对数据库进行划分时,每个业务对应一个数据库。

image.png

垂直分库优点:

  1. 降低单数据库服务的压力,增加系统可用性;
  2. 业务清晰,各系统间解耦合;
  3. 提升 IO 性能,增加数据库链接数以及其他硬件的瓶颈。

垂直分库缺点:

  1. 不同库之间的数据一致性无法保证,需要通过分布式事务;
  2. 依然存在单库、单表数据过大的问题,需要结合水平拆分;

1.2 垂直分表

垂直分表指将存在一张表中的不同字段拆分为多张表,是一种大表拆小表的模式。拆分后的表字段、结构均不同,组合一起则是原表。

一般是将经常修改的、数据较大的、不常查询的字段拆分到“扩展表”中,这样拆分以后核心表大多是访问频率较高的字段,而且字段长度也都较短,减少了查询时的磁盘 IO,提升数据库效率。

如下图,我们在进行下单时一般需要存储快照信息,该字段有长且不常使用,故拆分出来可提高订单信息的查询效率。

image.png

垂直分表优点:

  1. 降低表的数据规模,提升效率;
  2. 减少单条数据占用空间,减少磁盘 IO。

垂直分表缺点: 依然存在单表数据过大的问题,需要结合水平拆分;

2. 水平拆分

水平拆分包含水平分库和水平分表。

2.1 水平分库

水平分库是将数据库中的表数据按照某种规则拆分到多个库中,以实现水平扩展,提升数据库读写性能。

一般切分到不同的库中的表结构是相同的,表中数据不同,且伴随水平分表。

如下图,将DB-trade库中的 order 表水平切分到DB-trade 1DB-trade 2库中。

image.png

水平分库优点:

  1. 极大降低单库数据规模,提高系统高并发能力;
  2. 业务代码改动小,不需要拆分业务。

水平分库缺点:

  1. 跨库的 join 关联查询性能较差,增加开发复杂度;
  2. 单库的自增 ID 受影响。

2.2 水平分表

水平分表是将数据按照某种规则拆分到多张表,多张表还是属于一个库且结构相同。大大减少单表数据量,提升查询效率,但是对数据库的压力没有帮助

如下图,一张 order 订单表有 400 万数据,经过水平拆分出来 2 个表 order_1 和 order_2,每张表存有数据 200万,以此类推。

image.png

水平分表优点:

  1. 大大减少单表数据量,提升查询效率;
  2. 业务代码改动小,不需要拆分业务。

水平分表缺点: 多张表属于一个库,数据库的压力仍存在。

五、分库分表可能有哪些问题?

1. 事务问题

分库可能导致一次事务的执行的数据不在同一个服务器上,数据库层面无法实现所有服务的事务操作。可能会产生数据不一致的情况。

解决方案是通过分布式事务,来能最大限度保证了数据库操作的原子性,详情见我的另一篇文章分布式事务。

2. 主键唯一性问题

在数据库表设计时,经常会使用自增ID作为数据主键,这就导致后续在迁库迁表、或者分库分表操作时,会因为主键的变化或者主键不唯一产生冲突。

解决方案是通过一些策略生成全局唯一的分布式 ID,详情见我的另一篇文章分布式 ID

3. 跨库多表join问题

拆分之前,应用中很多列表或详情的数据可以通过 join 来完成,但是分库拆分后,数据可能分布在不同的服务器上,这种跨节点的 join 会有很多问题。

解决方案是避免挂库多表 join 的产生:

  1. 可以采用多次查询业务层进行数据组装;
  2. 将存在关联关系的表拆分在同一数据库下;
  3. 字段冗余避免 join 查询。

4. 跨库聚合查询问题

跨库进行聚合查询时,如 group by,order by 等,会变的异常复杂,导致常需要复杂的业务代码才能实现上述业务逻辑。

解决方案有:

  1. 业务代码中分别查询,然后组装数据(可能需要用一些排序算法优化效率);
  2. 使用专业的分布式框架,比如开源框架:ElasticSearch;

结语

本文主要讲述的是我们在开发过程中为什么需要分库分表,以及分库分表的场景、方案和可能出现的问题。因为一些内容的扩展点还有很多,放在一起影响阅读,本文只是简单的讲述了分库分表的一些基础知识,后续会针对分库分表分片方案、常用中间件的原理和使用,以及如何完整落地一个分库分表方案进行开展。


参考:

[1] 程序员小富. 好好的系统,为什么要分库分表?

[2] 鹅厂架构师. 一文读懂数据库分库分表.

与谈谈为什么要分库分表?相似的内容:

谈谈为什么要分库分表?

由于数据库的承载能力是有限的,当业务增长量达到一定规模后,数据库的性能就会达到瓶颈。于是产生了分库分表的解决方案,本文将详细讲解什么是分库分表,以及分库分表的原因和可能产生的问题。

为什么你学不会递归?谈谈我的经验

本文已收录到 GitHub · AndroidFamily,有 Android 进阶知识体系,欢迎 Star。技术和职场问题,请关注公众号 [彭旭锐] 进 Android 面试交流群。 前言 大家好,我是小彭。 今天分享到计算机科学中一个基础又非常重要的概念 —— 递归。递归是计算机中特有的概念,你

如何3分钟,快速开发一个新功能

背景 关于为什么做这个代码生成器,其实主要有两点: 参与的项目中有很多分析报表需要展示给业务部门,公司使用的商用产品,或多或少有些问题,这部分可能是历史选型导致的,这里撇开不不谈;项目里面也有很多CRUD的功能,而这些功能的实现代码基本上差不多,这些功能都去手写,也比较浪费时间而且效率很低,还可能会

分布式数据库架构路线大揭秘

摘要:这些年大家都在谈分布式数据库,各大企业也纷纷开始做数据库的分布式改造。那么所谓的分布式数据库是什么?采用什么架构,优势在哪?为什么越来越多企业选择它?我们不妨一起来深入了解下。 本文分享自华为云社区《GaussDB分布式架构大揭秘》,作者:华为云数据库首席架构师 冯柯。 这些年大家都在谈分布式

PHP 程序员是学 Swoole ?还是学 Go ?

这次为什么要讨论这个话题,因为 Swoole 和 Go 在 PHP 程序员坊间一直都是茶语饭后的谈资,觉得懂 Swoole 和 Go 的就高人一等。

[转帖]三篇文章了解 TiDB 技术内幕 - 谈调度

返回全部 申砾产品技术解读2017-06-06 为什么要进行调度 先回忆一下 三篇文章了解 TiDB 技术内幕 - 说存储 提到的一些信息,TiKV 集群是 TiDB 数据库的分布式 KV 存储引擎,数据以 Region 为单位进行复制和管理,每个 Region 会有多个 Replica(副本),这

为什么 Python 代码在函数中运行得更快?

哈喽大家好,我是咸鱼 当谈到编程效率和性能优化时,Python 常常被调侃为“慢如蜗牛” 有趣的是,Python 代码在函数中运行往往比在全局范围内运行要快得多 小伙伴们可能会有这个疑问:为什么在函数中运行的 Python 代码速度更快? 今天这篇文章将会解答大家心中的疑惑 原文链接:https:/

从DevOps实践落地的角度谈谈“流程”和“规范"的反模式

最近在经历的一些事情,让我突发灵感,觉得要写点关于DevOps体系建设过程中的“流程规范”,记录下来。 如何解读"流程规范" 谈到DevOps落地,无一例外都会提“流程规范“,我想没有人会反对,甚至会”不放在眼里“,因为概念本身没有什么晦涩难懂。可是一到落地,好像就是另外一番场景,“一地鸡毛”,“形

痞子衡嵌入式:对比恩智浦全系列MCU(包含Kinetis/LPC/i.MXRT/MCX)的GPIO电平中断设计差异

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦全系列MCU(包含Kinetis, LPC, i.MXRT, MCX)的GPIO电平中断设计差异。 在痞子衡旧文 《以i.MXRT1xxx的GPIO模块为例谈谈中断处理函数(IRQHandler)的标准流程》里,痞子衡主要介绍得是

谈谈Selenium中浏览器驱动的日志

谈谈Selenium中浏览器驱动的日志 来源于一位同学,“老师为啥firefox执行后会有日志文件,chrome没有呢?” 比对 你打开chrome浏览器 from selenium import webdriver driver = webdriver.Chrome() 这样是没有日志的 同样的代