连载中 1/20

单表两亿行:一次改了八小时的 DDL,逼出了分库分表

2026-07-18 · 2633 阅读 · 0 评论 · 0 赞

一张表的两亿行时刻

故事从一张订单表说起。业务跑了两三年,订单表两亿行,平时查询有索引护体,看起来岁月静好。直到产品要在订单上加一个「渠道来源」字段——DBA 拿着方案皱了半天眉:在线 DDL 工具全量拷表加回放增量,八小时起步;拷表期间磁盘要多占一份空间,主从延迟会全程飘红。最后 DBA 说了一句让人清醒的话:这不是慢,是这张表已经不配再被改了

单表规模逼近天花板时,问题从来不是一个,是一串:索引膨胀——B+ 树层级涨上去,每个查询多几次磁盘 IO;DDL 慢如老牛——任何结构变更都要全量拷表;备份窗口失控——全量备份跑不完一个夜里;磁盘与内存水位——Buffer Pool 装不下热数据,命中率往下掉。这一串问题互为帮凶,拖到最后就是线上事故。

什么规模才算到顶

先泼冷水:两亿行不等于必须拆。行数只是表象,真正的判断依据是「顶格优化之后还撑不撑得住」。行业里常见的参考线是:单表行数向千万级靠拢、单库数据量向 TB 级靠拢、QPS 向单实例瓶颈(万级上下)靠拢——三条里撞了两条,就该认真评估。但参考线只是提醒,不是判决,很多所谓「必须拆」的场景,把索引建对、把冷数据归档掉、把读流量分出去之后,还能再撑两年。

所以这个系列的第一课是克制:分库分表是高成本的重构,不是性能优化的第一步。它带来的复杂度——跨片查询、分布式事务、数据迁移、运维翻倍——会跟随系统余生。下一篇先把「拆之前还能做的三招」讲透,三招打完还顶不住,再来动刀。

拆库与拆表:两把不同的刀

「分库分表」四个字其实混着两种手术。分表:把一张大表切成多张结构相同的小表,可以只在一个实例里分(table_0 到 table_63),也可以分到多个实例。分表直接解决单表问题——索引层级、DDL 时长、行数规模;但如果这些表还住在同一个实例里,实例级的瓶颈(CPU、内存、磁盘、连接数、QPS 上限)一个都没解决

分库:把数据拆到多个 MySQL 实例上,每个实例独享 CPU、内存和磁盘,写能力与容量一起线性扩展。分库必然分表(每个实例上就是一张张小表),而分表不一定分库。所以真正的选型问题只有一个:瓶颈在表还是在实例?表大就分表,实例撑不住就分库,多数大系统最后两者都要——「N 库 M 表」的矩阵式拆法就是答案,比如 8 库 64 表,每个库 8 张。

动刀前的全景清单

确定要拆之后,决策链有五环,这个系列按这个顺序展开:怎么切——垂直还是水平,刀口选在哪(第 3-4 篇);键怎么定——分片键是终身选择(第 5 篇);路由怎么落——代码、代理还是 SDK(第 6-8 篇);查询怎么办——跨片聚合、分页、JOIN(第 9-10 篇);数据怎么迁——双写、校验、切流(第 14-15 篇)。每一步都有回头路,唯独分片键没有——它会锁死系统的查询能力很多年。

下一篇,先把刀放下,聊聊拆之前那三招顶格优化——很可能你的两亿行,瘦完身就不需要这一刀了。

503

10 年全栈工程师 · 503咖啡馆主理人

#分库分表#单表上限#分表分库#DDL#容量规划

评论 (0)

相关推荐

连载中 12/20

排查四件套:jstack、jmap、jstat、jcmd 的实战分工

jstack 看线程在干什么,jmap 看堆里装了什么,jstat 看运行时在变什么,jcmd 是统一入口。四把刀各管一段,配合着用没有查不动的现场。

#jstack#jmap#jstat#jcmd#排查工具
2026-09-16 · 4 阅读 · 0 评论 · 0 赞
连载中 11/20

GC 日志:把回收过程翻译成人话

一行 GC 日志里塞着七种信息:谁触发的、收了哪、停了多久、活了哪些。加上 -Xlog 配置,再加上日志分析工具,GC 不再是只能盯监控曲线的黑盒。

#GC日志#Xlog#日志分析#GC监控#Full GC排查
2026-09-16 · 13 阅读 · 0 评论 · 0 赞
连载中 10/20

ZGC:亚毫秒停顿是怎么炼成的

百 G 大堆停顿不到一毫秒,靠的是把搬家全部挪到并发阶段——着色指针让引用自带状态,读屏障让搬运中的对象依然可访问。代价是吞吐与内存,收益是停顿与堆大小解耦。

#ZGC#着色指针#读屏障#亚毫秒停顿#分代ZGC
2026-09-15 · 8 阅读 · 0 评论 · 0 赞