0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

你们知道为什么要分库分表吗

上海磐启微电子有限公司 来源:爱笑的架构师 作者:雷架 2021-08-16 10:37 次阅读

在文章开头先抛几个问题:

(1)什么时候才需要分库分表呢?我们的评判标准是什么?

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

(3)数据增长速度很快,每天产生多少数据,才需要考虑做分库分表?

这些问题你都搞清楚了吗?相信看完这篇文章会有答案。

为什么要分库分表?

首先回答一下为什么要分库分表,答案很简单:数据库出现性能瓶颈。用大白话来说就是数据库快扛不住了。

数据库出现性能瓶颈,对外表现有几个方面:

大量请求阻塞

在高并发场景下,大量请求都需要操作数据库,导致连接数不够了,请求处于阻塞状态。

SQL 操作变慢

如果数据库中存在一张上亿数据量的表,一条 SQL 没有命中索引会全表扫描,这个查询耗时会非常久。

存储出现问题

业务量剧增,单库数据量越来越大,给存储造成巨大压力。

从机器的角度看,性能瓶颈无非就是CPU、内存、磁盘、网络这些,要解决性能瓶颈最简单粗暴的办法就是提升机器性能,但是通过这种方法成本和收益投入比往往又太高了,不划算,所以重点还是要从软件角度入手。

数据库相关优化方案

数据库优化方案很多,主要分为两大类:软件层面、硬件层面。

软件层面包括:SQL 调优、表结构优化、读写分离、数据库集群、分库分表等;

硬件层面主要是增加机器性能。

SQL 调优

SQL 调优往往是解决数据库问题的第一步,往往投入少部分精力就能获得较大的收益。

SQL 调优主要目的是尽可能的让那些慢 SQL 变快,手段其实也很简单就是让 SQL 执行尽量命中索引。

开启慢 SQL 记录

如果你使用的是 Mysql,需要在 Mysql 配置文件中配置几个参数即可。

slow_query_log=on

long_query_time=1

slow_query_log_file=/path/to/log

调优的工具

常常会用到 explain 这个命令来查看 SQL 语句的执行计划,通过观察执行结果很容易就知道该 SQL 语句是不是全表扫描、有没有命中索引。

select id, age, gender from user where name = ‘爱笑的架构师’;

返回有一列叫“type”,常见取值有:

ALL、index、range、 ref、eq_ref、const、system、NULL(从左到右,性能从差到好)

ALL 代表这条 SQL 语句全表扫描了,需要优化。一般来说需要达到range 级别及以上。

表结构优化

以一个场景举例说明:

“user”表中有 user_id、nickname 等字段,“order”表中有order_id、user_id等字段,如果想拿到用户昵称怎么办?一般情况是通过 join 关联表操作,在查询订单表时关联查询用户表,从而获取导用户昵称。

但是随着业务量增加,订单表和用户表肯定也是暴增,这时候通过两个表关联数据就比较费力了,为了取一个昵称字段而不得不关联查询几十上百万的用户表,其速度可想而知。

这个时候可以尝试将 nickname 这个字段加到 order 表中(order_id、user_id、nickname),这种做法通常叫做数据库表冗余字段。这样做的好处展示订单列表时不需要再关联查询用户表了。

冗余字段的做法也有一个弊端,如果这个字段更新会同时涉及到多个表的更新,因此在选择冗余字段时要尽量选择不经常更新的字段。

架构优化

当单台数据库实例扛不住,我们可以增加实例组成集群对外服务。

当发现读请求明显多于写请求时,我们可以让主实例负责写,从实例对外提供读的能力;

如果读实例压力依然很大,可以在数据库前面加入缓存如 redis,让请求优先从缓存取数据减少数据库访问。

缓存分担了部分压力后,数据库依然是瓶颈,这个时候就可以考虑分库分表的方案了,后面会详细介绍。

硬件优化

硬件成本非常高,一般来说不可能遇到数据库性能瓶颈就去升级硬件。

在前期业务量比较小的时候,升级硬件数据库性能可以得到较大提升;但是在后期,升级硬件得到的收益就不那么明显了。

分库分表详解

下面我们以一个商城系统为例逐步讲解数据库是如何一步步演进。

单应用单数据库

在早期创业阶段想做一个商城系统,基本就是一个系统包含多个基础功能模块,最后打包成一个 war 包部署,这就是典型的单体架构应用。

如上图,商城系统包括主页 Portal 模板、用户模块、订单模块、库存模块等,所有的模块都共有一个数据库,通常数据库中有非常多的表。

因为用户量不大,这样的架构在早期完全适用,开发者可以拿着 demo到处找(骗)投资人。

一旦拿到投资人的钱,业务就要开始大规模推广,同时系统架构也要匹配业务的快速发展。

多应用单数据库

在前期为了抢占市场,这一套系统不停地迭代更新,代码量越来越大,架构也变得越来越臃肿,现在随着系统访问压力逐渐增加,系统拆分就势在必行了。

为了保证业务平滑,系统架构重构也是分了几个阶段进行。

第一个阶段将商城系统单体架构按照功能模块拆分为子服务,比如:Portal 服务、用户服务、订单服务、库存服务等。

如上图,多个服务共享一个数据库,这样做的目的是底层数据库访问逻辑可以不用动,将影响降到最低。

多应用多数据库

随着业务推广力度加大,数据库终于成为了瓶颈,这个时候多个服务共享一个数据库基本不可行了。我们需要将每个服务相关的表拆出来单独建立一个数据库,这其实就是“分库”了。

单数据库的能够支撑的并发量是有限的,拆成多个库可以使服务间不用竞争,提升服务的性能。

如上图,从一个大的数据中分出多个小的数据库,每个服务都对应一个数据库,这就是系统发展到一定阶段必要要做的“分库”操作。

现在非常火的微服务架构也是一样的,如果只拆分应用不拆分数据库,不能解决根本问题,整个系统也很容易达到瓶颈。

分表

说完了分库,那什么时候分表呢?

如果系统处于高速发展阶段,拿商城系统来说,一天下单量可能几十万,那数据库中的订单表增长就特别快,增长到一定阶段数据库查询效率就会出现明显下降。

因此,当单表数据增量过快,业界流传是超过500万的数据量就要考虑分表了。当然500万只是一个经验值,大家可以根据实际情况做出决策。

那如何分表呢?

分表有几个维度,一是水平切分和垂直切分,二是单库内分表和多库内分表。

水平拆分和垂直拆分

就拿用户表(user)来说,表中有7个字段:id,name,age,sex,nickname,description,如果 nickname 和 description 不常用,我们可以将其拆分为另外一张表:用户详细信息表,这样就由一张用户表拆分为了用户基本信息表+用户详细信息表,两张表结构不一样相互独立。但是从这个角度来看垂直拆分并没有从根本上解决单表数据量过大的问题,因此我们还是需要做一次水平拆分。

还有一种拆分方法,比如表中有一万条数据,我们拆分为两张表,id 为奇数的:1,3,5,7……放在 user1, id 为偶数的:2,4,6,8……放在 user2中,这样的拆分办法就是水平拆分了。

水平拆分的方式也很多,除了上面说的按照 id 拆表,还可以按照时间维度取拆分,比如订单表,可以按每日、每月等进行拆分。

每日表:只存储当天的数据。

每月表:可以起一个定时任务将前一天的数据全部迁移到当月表。

历史表:同样可以用定时任务把时间超过 30 天的数据迁移到 history表。

总结一下水平拆分和垂直拆分的特点:

垂直切分:基于表或字段划分,表结构不同。

水平切分:基于数据划分,表结构相同,数据不同。

单库内拆分和多库拆分

拿水平拆分为例,每张表都拆分为了多个子表,多个子表存在于同一数据库中。比如下面用户表拆分为用户1表、用户2表。

在一个数据库中将一张表拆分为几个子表在一定程度上可以解决单表查询性能的问题,但是也会遇到一个问题:单数据库存储瓶颈。

所以在业界用的更多的还是将子表拆分到多个数据库中。比如下图中,用户表拆分为两个子表,两个子表分别存在于不同的数据库中。

一句话总结:分表主要是为了减少单张表的大小,解决单表数据量带来的性能问题。

分库分表带来的复杂性

既然分库分表这么好,那我们是不是在项目初期就应该采用这种方案呢?不要激动,冷静一下,分库分表的确解决了很多问题,但是也给系统带来了很多复杂性,下面简要说一说。

(1)跨库关联查询

在单库未拆分表之前,我们可以很方便使用 join 操作关联多张表查询数据,但是经过分库分表后两张表可能都不在一个数据库中,如何使用 join 呢?

有几种方案可以解决:

字段冗余:把需要关联的字段放入主表中,避免 join 操作;

数据抽象:通过ETL等将数据汇合聚集,生成新的表;

全局表:比如一些基础表可以在每个数据库中都放一份;

应用层组装:将基础数据查出来,通过应用程序计算组装;

(2)分布式事务

单数据库可以用本地事务搞定,使用多数据库就只能通过分布式事务解决了。

常用解决方案有:基于可靠消息(MQ)的解决方案、两阶段事务提交、柔性事务等。

(3)排序、分页、函数计算问题

在使用 SQL 时 order by, limit 等关键字需要特殊处理,一般来说采用分片的思路:

先在每个分片上执行相应的函数,然后将各个分片的结果集进行汇总和再次计算,最终得到结果。

(4)分布式 ID

如果使用 Mysql 数据库在单库单表可以使用 id 自增作为主键,分库分表了之后就不行了,会出现id 重复。

常用的分布式 ID 解决方案有:

UUID

基于数据库自增单独维护一张 ID表

号段模式

Redis 缓存

雪花算法(Snowflake)

百度uid-generator

美团Leaf

滴滴Tinyid

这些方案后面会写文章专门介绍,这里不再展开。

(5)多数据源

分库分表之后可能会面临从多个数据库或多个子表中获取数据,一般的解决思路有:客户端适配和代理层适配。

业界常用的中间件有:

shardingsphere(前身 sharding-jdbc)

Mycat

总结

如果出现数据库问题不要着急分库分表,先看一下使用常规手段是否能够解决。

分库分表会给系统带来巨大的复杂性,不是万不得已建议不要提前使用。作为系统架构师可以让系统灵活性和可扩展性强,但是不要过度设计和超前设计。在这一点上,架构师一定要有前瞻性,提前做好预判。大家学会了吗?

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10392

    浏览量

    206418
  • 数据
    +关注

    关注

    8

    文章

    6508

    浏览量

    87525
  • SQL
    SQL
    +关注

    关注

    1

    文章

    737

    浏览量

    43447
  • 磁盘
    +关注

    关注

    1

    文章

    336

    浏览量

    24871

原文标题:我们为什么要分库分表?

文章出处:【微信号:gh_6a53af9e8109,微信公众号:上海磐启微电子有限公司】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    CYW43455带有7ACL 路的设备有什么作用吗?

    吗? (1 个中央连接到 7 个外围设备,还是 1 个外围设备到 7 个中央?) 2. 如果它不能组成最多 7 个链接,有什么修改的指导链接吗? 什么将仅限于链接号? 3。我能知道为什么我在 ble 数据中找不到描述的 AC
    发表于 03-01 09:08

    通信电源系统是如何工作的?-48 V电源是如何产生的?

    在我国,通信电源大部分都是使用-48 V供电,作为通信人,你知道为什么吗?
    的头像 发表于 12-21 09:39 1039次阅读
    通信电源系统是如何工作的?-48 V电源是如何产生的?

    有谁知道为什么AD7712的DRDY引脚一直是高电平吗?

    有谁知道为什么AD7712的DRDY引脚一直是高电平吗?它不是一上电就一直工作即使没有输入,它的DRDY引脚应该会周期性的变为低电平啊?一直是高电平也就没有数据输出了。
    发表于 12-13 07:41

    PCB叠层设计有两个铁规矩,你知道为什么吗?

    而且,没有交替设置的PCB在传输信号时可能发生更多的噪音和辐射,这是因为没有考虑到不同材料的电磁特性,当信号通过不同材料时,可能会引发反射、折射等现象,导致噪音增加。
    的头像 发表于 10-09 16:14 241次阅读

    数据库分区、分库和分表

    今天先说说数据库的数据分区,分库以及分表的内容吧! 数据库分区、分库和分表 数据库分区、分库和分表是针对大型数据库系统的优化策略。它们的主要目的是提高数据库的性能和可靠性,以满足不断增长的数据存储
    的头像 发表于 09-30 11:24 800次阅读

    使用STM32F030移植STemwin5.28驱动SSD1315时有部分库函数无法使用的问题

    使用STM32F030移植STemwin5.28驱动SSD1315时有部分库函数无法使用 比如clear函数和CreateFramewin函数无法使用,但是显示字符串函数和检测运行内存都函数可以使用
    发表于 08-07 11:39

    你们知道什么是光纤直放站吗?

    在林宝分享的各种案例中 为啥无线直放站,一台机就能搞定信号覆盖? 而光纤直放站需要配置近端、远端两台机呢? 是不是业务员拿我当“韭菜”呢! 且听林宝慢慢道来↓↓↓ 01 光纤直放站的组成部分 光纤直放站主要由近端光纤机、光纤线、远端光纤机、馈线、接收发射天线五个部分组成。 02 光纤机的工作原理 无线信号从基站中耦合出来后,进入近端光纤机,近端光纤机把射频信号转变为光信号,再通过光纤线传输至远端光纤机,远端光纤机把光
    的头像 发表于 07-24 16:30 642次阅读

    知道为什么有的处理器会漏电?

    在我的上一篇文章中,我谈到了一个功耗过小的器件――是的,的确有这种情况――带来麻烦的事情。但这种情况很罕见。我处理的更常见情况是客户抱怨器件功耗大于数据手册所宣称的值。
    的头像 发表于 07-23 15:11 290次阅读
    你<b class='flag-5'>知道为</b>什么有的处理器会漏电?

    知道为什么不用XFP光模块了吗?

    在光纤通信应用领域中,10G光模块凭借着较低的成本和功耗被广泛应用于学校、企业等应用场景中。XFP和SFP+是10G光模块常见的两种封装类型,那为什么现在市场上XFP光模块应用比较少了呢?
    的头像 发表于 07-12 14:51 552次阅读
    你<b class='flag-5'>知道为</b>什么不用XFP光模块了吗?

    Espress通过uart模块连接计算机并将CH_PD上拉到VCC,不知道为什么总是完好无损的回来?

    我从现场购买了 Espress 生产的 我通过 uart 模块连接计算机并将 CH_PD 上拉到 VCC。接下来,我通过串口助手向它发送指令。但是,不知道为什么总是完好无损的回来。有什么不对吗? 请帮忙!
    发表于 06-09 08:33

    知道为什么要用PLC吗!

    plc
    YS YYDS
    发布于 :2023年06月01日 22:47:59

    分库分表的21条法则速来码住(下)

    还是不着急实战,咱们先介绍下在分库分表架构实施过程中,会接触到的一些通用概念,了解这些概念能够帮助理解市面上其他的分库分表工具,尽管它们的实现方法可能存在差异,但整体思路基本一致。因此,在开始
    的头像 发表于 05-26 17:33 463次阅读
    <b class='flag-5'>分库</b>分表的21条法则速来码住(下)

    分库分表的21条法则速来码住(上)

    还是不着急实战,咱们先介绍下在分库分表架构实施过程中,会接触到的一些通用概念,了解这些概念能够帮助理解市面上其他的分库分表工具,尽管它们的实现方法可能存在差异,但整体思路基本一致。因此,在开始
    的头像 发表于 05-26 17:33 387次阅读
    <b class='flag-5'>分库</b>分表的21条法则速来码住(上)

    你们知道闪存如何工作的吗

    我们在计算机上可以存储和传输各种文件——数码照片、音乐文件、文字处理文档、PDF 和无数其他形式的媒体。 但有时计算机的硬盘驱动器并不完全是你想要获取信息的地方。 无论是想为系统外的文件制作备份副本,还是担心系统的安全,使用一种称为闪存的电子存储器的便携式存储设备是好的解决办法。 电子存储器有多种形式,可用于多种用途。 闪存用于在计算机、数码相机和家用视频游戏机中方便快捷地存储信息。 它更像是一个硬盘驱动器,而不是 RAM。
    的头像 发表于 05-22 17:33 426次阅读
    <b class='flag-5'>你们</b><b class='flag-5'>知道</b>闪存如何工作的吗

    放大电路为什么单端输入和双端输入?

    放大电路为什么单端输入和双端输入?两者有什么本质上的区别?如何区分这两种电路?
    发表于 05-06 10:43