【面试】一文搞懂MySQL的分库分表!

        MySQL 分库分表是一种数据库优化手段,通常用于应对数据量巨大、并发量高的场景。随着系统数据的增长,单个数据库可能难以承受高负载,进而影响性能和可扩展性。分库分表的目标是将数据分散到多个库或表中,从而减少单一库或表的压力,提高系统性能。

目录

一 我们为什么要分库分表?

二 怎么分:水平拆分与垂直拆分

三 如何进行分库分表操作

一 我们为什么要分库分表?

1.性能问题

  • 数据量过大:当单个表的数据量非常大时,查询、插入、更新等操作的性能会明显下降。MySQL 性能通常随着单表数据量的增加而下降,数百万、数千万甚至更大的数据量可能导致响应时间变慢。
  • 并发读写压力:当大量用户同时进行读写操作时,单个数据库实例可能承受不了高并发,造成数据库瓶颈和宕机风险。

2.扩展性问题

  • 存储瓶颈:数据库存储有上限,不可能无限扩展单个数据库实例的存储容量。如果数据量增长到单个数据库服务器难以承载的规模,就需要对数据进行切分。
  • 数据库维护成本高:随着数据量和并发的增加,备份、恢复、迁移等运维工作会变得越来越困难和耗时。

3.业务需求

        当业务快速发展,数据量和用户量急剧增加时,使用分库分表可以保证系统的扩展性和高可用性。

二 怎么分:水平拆分与垂直拆分

1. 垂直拆分(竖着分)

        垂直拆分是基于表的字段进行拆分,将一个表中的不同列拆分到不同的库或表中,通常用于优化查询效率、减少数据冗余。

        分表之后,每个表的结构、数据都不一样,所有表的数据构成了原始数据集。通常表与表之间会存在至少一个关联字段,用于连接多表。

        适用场景:

        当表的列非常多时(上百列),部分列经常被使用,而其他列很少被访问。这时将常用的列和不常用的列分开存储,能够提高查询效率,减少数据冗余和磁盘 I/O。

        表中的一些列较大且少用(如大字段、大文本、Blob 字段等),可以将这些字段独立出来存储,避免影响经常使用的字段的查询性能。

        例如对于一个用户表 user,包含用户的基本信息(如 id、name、email 等)和扩展信息(如详细地址、头像、个人简介等),可以将用户的基本信息和扩展信息分到不同的表中。

user_basic(id, name, email)        -- 常用字段
user_extra(id, address, avatar, bio) -- 不常用字段

        垂直拆分可以减少表的宽度,也就是减少每次查询时扫描的字段,提升查询效率,同时将不同业务模块分开,便于开发和维护。

         但是垂直拆分后需要额外的维护成本,如拆分后需要处理关联查询,增加开发复杂度;拆分后可能依然无法解决单表行数过大的问题,仍需要水平拆分来进一步优化。

2.水平拆分(横着分)

        水平拆分是基于表的行进行拆分,将同一个表中的不同数据分布到不同的库或表中。常用于解决单表数据量过大、查询和写入性能问题。

        拆分后,每个表的结构是一样的,但是数据独立,均不一样,没有交集,所有表的数据共同构成了全部原始数据。

        适用场景:

        当单个表中的数据量非常大,导致查询、写入性能下降时。水平拆分能将数据分布到多个表或库中,减轻单表的负担。

        适合业务规模扩展较大、用户群体广泛的数据处理场景,如电商、社交平台等。

        例如有一个订单表 order,每天有成千上万条订单记录,可以根据订单号、用户 ID、时间等字段对表进行水平拆分。

order_2021(id, user_id, order_amount, order_date)
order_2022(id, user_id, order_amount, order_date)

        MySQL水平拆分通常使用的数据分片策略有两种:

        1)范围分片:按时间、ID范围等,将数据切分到不同表或库中。

        2)哈希分片:通过对某个字段(如用户 ID 或订单 ID)取哈希值,将数据均匀地分布到多个表或库中。

        水平分片有利于分散数据压力,解决单表数据量过大、查询速度慢的问题,提升数据库的性能,而且可以根据业务规模的变化,逐渐增加新的分库或分表来扩展系统的容量,具有很强的扩展性。但是开发和运维的复杂性增加,因为当进行查询和插入操作时,需要额外逻辑判断该访问哪个库或表,而且会涉及分布式事务。

三 如何进行分库分表操作

1.判断是横向拆分还是纵向拆分

        如果某些字段比较独立且较少被访问,或者表的字段特别多(几十甚至上百个),且访问时经常只需要部分字段,可以考虑垂直拆分。

        如果表的行数非常大,影响了查询和写入性能,或者业务需求导致数据量增长迅速,预计将来会超过单表或单库的处理能力,可以考虑水平拆分。

2.拆分数量的判断

        我们可以根据业务逻辑的模块、字段的访问频率等进行拆分,经常访问的字段可以保留在一个表中,较少访问或大字段(如图片、文档)可以独立拆分出去。

        水平拆分可以根据表的数量进行预测,例如,如果预计未来数据量为 1 亿条,单表容量限制为 1000 万,则需要拆分为 10 个表。或者结合系统并发量、服务器容量和架构而定。

3.如何实现均匀拆分

        哈希取模:根据某个字段(如用户 ID、订单 ID)取哈希值,然后对拆分表的数量取模,将数据分布到不同表或库中。哈希取模是一种非常常用的分片策略,能够确保数据均匀分布。

        范围分片:根据某个字段的值范围进行划分,将数据分布到不同表中。例如根据订单日期进行分片。

        一致性哈希:使用一致性哈希算法来分配数据,可以动态增加或减少节点(表或库),并且能保证数据分布均匀,适用于分布式系统中。

        选择合理的分片键:分片键应当是查询时常用的字段,并且其值的分布要尽量均匀。避免选择高度聚集的字段(如创建时间、递增 ID 等),否则会导致数据倾斜。

        避免热点:在某些情况下,特定的数据可能会成为访问热点,导致部分表或库的访问频率过高。为了避免这种情况,可以使用合理的分片策略(如哈希分片)来均衡负载。

        动态扩容:当数据量持续增长,可以考虑通过增加分片表的数量来进行扩容。为了避免在扩容过程中发生数据倾斜,可以采用一致性哈希等动态分片算法。

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值