MySQL 分库分表:一篇讲透,解决数据量过大的性能瓶颈
当 MySQL 单表数据量达到千万级甚至亿级,不管加多少索引、怎么优化 SQL,查询都会越来越慢 —— 这时候,分库分表就是唯一的解决方案。
很多人觉得分库分表复杂、不敢碰;今天用最直白的方式,把分库分表的核心逻辑、方案、坑点讲透,新手也能理解。
一、先搞懂:为什么要分库分表?
单库单表的性能瓶颈:
- 单表数据量过大,索引失效、查询扫描行数暴增
- 数据库连接数、IO、CPU 达到上限
- 大表 DDL(加字段、改索引)会锁表,业务直接卡死
分库分表的核心目的:把 “大而慢” 的库 / 表,拆成 “小而快” 的库 / 表,分散压力、提升性能。
二、分库分表的核心分类
1. 垂直拆分(按业务拆分)
垂直分表(单表拆多表)
把一张字段多的表,按业务维度拆成多张表:
- 例子:user 表拆成 user_base(基础信息:id、name、age)和 user_ext(扩展信息:avatar、address、remark)
- 适用场景:表字段过多,部分字段访问频率低
垂直分库(单库拆多库)
把一个数据库,按业务模块拆成多个数据库:
- 例子:电商库拆成 user_db(用户)、order_db(订单)、goods_db(商品)
- 适用场景:单库压力大,不同业务模块耦合度低
2. 水平拆分(按数据拆分)
把同一份数据,按规则分散到多个库 / 表中(核心!):
- 例子:order 表按用户 ID 哈希,拆成 order_01、order_02…order_16
- 核心:所有表结构完全一致,数据分散存储
- 适用场景:单表数据量超千万 / 亿级,查询慢、更新慢
三、水平拆分的核心规则(实战常用)
表格
拆分规则 | 实现方式 | 优点 | 缺点 |
哈希拆分 | 按用户 ID / 订单 ID 哈希取模:id % 分表数 | 数据分布均匀,查询快 | 扩容麻烦(需重新哈希) |
范围拆分 | 按时间 / ID 范围:如订单按月份拆、ID 1-1000 万放表 1 | 扩容简单,符合业务习惯 | 数据易倾斜(热点月份 / ID 段压力大) |
地理拆分 | 按用户地区:华东 / 华北 / 华南分库
| 符合业务场景,降低跨区域延迟 | 数据分布不均 |
实战首选:哈希拆分
plaintext
-- 示例:按用户ID分16张表,计算规则表名 = "order_" + (user_id % 16)-- user_id=100 → 100=4 → 存入order_04-- user_id=200 → 200=8 → 存入order_08四、分库分表的坑点(避坑指南)
- 跨库联表查询:拆分后无法直接 JOIN,需业务层二次查询
- 分布式事务:跨库更新数据,需用 Seata/TCC 等方案保证一致性
- 分页查询:跨表分页(如查第 100 页订单)需聚合所有表数据,性能差
- 扩容难题:哈希拆分扩容需迁移数据,建议提前规划分表数(如 16/32/64)
- 主键生成:自增 ID 失效,需用雪花算法生成全局唯一 ID
五、分库分表工具(不用重复造轮子)
- 轻量级:Sharding-JDBC(应用层代理,无中间件,易集成)
- 重量级:MyCat/ProxySQL(数据库代理层,适合大型集群)
- 云原生:阿里云 DRDS、腾讯云 TDSQL(托管方案,省心)
六、一句话总结
分库分表不是 “银弹”,而是数据量达到瓶颈后的 “必选项”:
- 先垂直拆分(解耦),后水平拆分(分散压力)
- 优先用哈希拆分,提前规划扩容
- 借助成熟工具,避开分布式事务、跨库查询坑点
纵使一路跌撞满身风霜,仍要在沉默里默默变强,所有难熬的时刻,终会成就更稳的自己。
文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有
