2亿行降到8000万|我放弃分库分表,用分区归档解决了

简介: 从接手 2 亿行订单表撞上查询慢、DDL 跑不完、备份窗口爆炸切入,先量热数据占比、写入增长、合规保留期三个数,再用时间分区 + 分区裁剪 + pt-archiver 分批归档 + 归档对账把存量清掉,并给出冷热分离三层架构与三个真实踩坑,最后说明归档是清存量、分库分表才是扩流量。

大家好,我是数据库小学妹👋 我踩过的坑,你别再踩。

去年我接手一个订单库,主表 2 亿行。接手第一周就撞上三件事。查最近一个月的订单,要从 2 亿行里翻,慢。想加个联合索引,DDL 排了两个小时还没跑完。做一次全备,备份窗口一路撑到凌晨五点。

我当时的第一反应是上分库分表。方案都写了一半,被组里一个老同事拦下来。他只问了我一句,这两亿行里,过去一年的有多少。我去查了一下只有 8000 多万,也就是说,有一亿两千多万行,是没人查的。

先量数,别急着动刀

那句话点醒我了。我当时默认"表大"就得"分表",却没搞清楚一件事,表大到底是存量还是流量。存量是历史数据堆出来的,流量是当前写入和查询的规模,这两个问题的解法压根不一样。分库分表解决的是流量,把一个库的写入和容量摊到多个库上。可如果这两亿行里大半是历史数据,那你压根没碰上流量的天花板,你碰上的是存量。所以动手前先量三个数。

要量的东西 怎么量 量出来说明什么
热数据占比 统计近 N 个月查询命中的时间范围 占比低,说明大部分数据没人查
写入增长 每月新增行数与增速 增速平缓,容量问题就不急
合规保留期 问业务和法务,数据要留多久 决定能不能删,能删到哪一年

从那次之后,我动大表前先把这三个数量出来。少一个,我都不敢往下写方案。存量还是流量,基本量完就分清了。

第一步不是删,是分区

我把那张表改成了按时间做 RANGE 分区,一个月一个分区。改分区时撞上一个硬约束,我事先不知道。InnoDB 要求分区键必须出现在表的每一个唯一索引里,所以主键不能只有 id,得改成 (id, created_at)。

-- 分区键必须进每一个唯一键,所以主键是复合的
CREATE TABLE orders (
    id         BIGINT NOT NULL,
    created_at DATETIME NOT NULL,
    order_no   VARCHAR(32) NOT NULL,
    user_id    BIGINT NOT NULL,
    amount     DECIMAL(12,2) NOT NULL,
    PRIMARY KEY (id, created_at),
    UNIQUE KEY uk_order_no (order_no, created_at)
)
PARTITION BY RANGE COLUMNS(created_at) (
    PARTITION p2025_01 VALUES LESS THAN ('2025-02-01'),
    PARTITION p2025_02 VALUES LESS THAN ('2025-03-01'),
    PARTITION p2025_03 VALUES LESS THAN ('2025-04-01')
);

这里有个语义变化,我一开始没留意。uk_order_no 加上 created_at 之后,它保证的就不再是订单号全局唯一了。同一个订单号,只要时间不同,就能插进去两条。这个唯一性得靠业务层或者其他机制补回来。约束反而是变松的,这点得心里有数。

分区做完,两处都松了。带时间范围的查询会做分区裁剪,只扫它需要的那个分区,不再全表翻。更关键的是归档,它变成了一个元数据操作。

-- 归档一个月,秒级完成,不逐行删
ALTER TABLE orders DROP PARTITION p2025_01;

这两条路的代价差得很远。走 DELETE FROM orders WHERE created_at < '2025-02-01',上亿行要删,undo 和 binlog 能把你写爆,主从延迟直接起飞,删完表空间还不还你。DROP PARTITION 是把那个分区的文件直接丢掉,快得多,也不产生海量日志。

分区裁剪也有前提,查询里得带上分区键。我们有些接口是按 user_id 查的,没带时间。那种查询在分区表上会扫全部三十几个分区,比不分区还慢。这类接口我后来单独补了时间范围参数,没补的干脆没资格上分区表。

第二步,把数据搬到该去的地方

DROP PARTITION 是删。删之前,数据得先搬走。

# pt-archiver:分批归档,避免大事务和主从延迟
pt-archiver \
  --source h=主库,D=order_db,t=orders \
  --dest   h=归档库,D=order_archive,t=orders \
  --where "created_at < '2025-02-01'" \
  --limit 1000 \
  --commit-each \
  --sleep 0.5

这几个参数是保命的。--limit 1000 让每次只搬一千行,事务短。--sleep 0.5 在批次之间歇一下,给主从复制留出追赶时间。--commit-each 保证每批都提交,不留长事务。我第一版没加 --sleep,跑起来主从延迟直接飙到几分钟,归档任务把主库的写入压力顶上去,从库追不上。加了 sleep 之后慢是慢了点,但稳。

搬到哪,看这些数据还要不要被人查。归档表如果还在同一个库,那只是把热表清空,存量压力一点没少。我们最后分了三层。

数据 放哪 还要查吗
热数据,近 3 个月 主库,SSD 天天查
温数据,3 个月到 2 年 归档库,普通盘 偶尔查,走独立接口
冷数据,2 年以上 列存/分析库 只做报表,不做点查

冷的那部分我们扔进了分析库。交易库做点查快,做分析型查询本来就不擅长,让列存去干更合适。这块我单独写过一篇,讲为什么 MySQL 做报表这么慢。

一致性怎么保证

搬数据最怕丢和重,我们给归档任务加了两道闸。第一道是主键去重。归档的目标表主键和源表一样,搬重复了唯一键会拦住,不会写进去两条。第二道是对账,归档跑完不直接删源数据,先比一遍。

-- 归档区与源分区各算一次,对上了才允许 DROP
SELECT COUNT(*) AS cnt, SUM(amount) AS total
FROM orders PARTITION (p2025_01);

SELECT COUNT(*) AS cnt, SUM(amount) AS total
FROM order_archive.orders
WHERE created_at >= '2025-01-01'
  AND created_at <  '2025-02-01';

行数和金额汇总都对得上,才执行 DROP PARTITION。这条是我从一次归档事故里学来的。那次少了几百行,原因是任务中途被重启,边界条件没写对,把当天的数据一起圈进去了。

归档完之后

三个月下来,主表从 2 亿行降到 8000 多万行。带时间范围的查询走分区裁剪,扫描行数下来了。DDL 终于能排进窗口,之前要两个多小时的加索引,现在四十多分钟。全备时长也回落了,备份窗口从凌晨五点缩回两点多。

但我要说句实话。归档不是万能的,它清的是存量。这张表每个月还在新增五六百万行,写 QPS 也一直在涨。哪天真顶到单机天花板,那还是得回到分库分表那条路上去。只是现在,还远没到。

避坑清单

DROP PARTITION 快,但它也是 DDL,一样要拿 MDL。执行前先看一眼有没有长事务在跑。我们有次在业务小高峰执行,一个报表长事务卡在那儿,DROP 一直等,后面的 INSERT 全堵在队列里。现在这条操作写进了我们的变更流程,只能走低峰窗口。

归档任务得能断点续跑。被重启、被 kill、断网,这些都躲不掉。我们的做法是每次记录归档到的最大主键和时间边界,重启后从边界往后接着搬,不从头再来。在亿级表上从头重跑,就是一场灾难。

还有一条。DELETE 删不掉表空间。如果因为某些原因你用不了分区,只能走 DELETE,那删完记得看一眼表空间还回来了没有。多半没有。你得重建表才能真把空间交还给操作系统,而重建本身又要一份等量的临时空间。所以规划磁盘的时候,别按"删完就省出来"来算。

写在最后

这期我想说的其实只有一句。表大不等于要分库分表。先看清楚,大的是存量还是流量。

存量大了,做个分区,把历史数据搬到该去的地方,多半就够了。要是流量真到顶,单机的写入和容量扛不住,那才轮到分库分表上场。这两件事的解法、成本、风险都不一样,混着看就会做错决策。

我写方案那次差点就错在这儿。拦我的老同事其实只问了一个问题,这两亿行里过去一年的有多少。问题问对了,方向自己就出来了。后来再有人拿方案来找我,我也先问这一句,量过没有。

你们手上最大的那张表,现在多少行?热数据占了多大比例?评论区聊聊。

我是数据库小学妹,帮你少走弯路少踩坑,咱们下篇见👋

相关文章
|
7天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
6950 9
|
5天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
1400 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
6天前
|
人工智能 并行计算 PyTorch
秋叶 ComfyUI 2026 整合包 v3.2 完整部署教程:Python 3.13 + Torch 2.13 全栈升级
秋叶aaaki ComfyUI 2026年8月整合包v3.2正式发布!全面升级Python 3.13.11、PyTorch 2.13.0+cu130及ComfyUI v0.30.2,原生支持MiniMax H3、Wan 2.2、Qwen-Image-2.1等2026主流音视频/图像模型,解压即用,无需环境配置。
869 5
|
19天前
|
人工智能 自然语言处理 安全
阿里云千问办公 QwenWork详细介绍:产品核心能力、典型场景、价格及常见问题解答
千问办公是阿里云推出的一站式AI办公平台,主打"不止于对话,更注重交付",依托通义千问旗舰大模型,用户一句话即可完成数据分析、PPT生成、视频剪辑等复杂任务,直接输出可用成果。产品深度打通钉钉生态与企业OA,覆盖桌面端、网页端,提供企业标准版198元/人/月等多档订阅方案,新用户注册即赠2000积分,适配工程师、HR、财务等多职业办公场景,成为能动手干活的"全能AI同事"。
3440 10
|
14天前
|
缓存 IDE Java
【保姆级】Android Studio下载、安装和汉化教程(2026最新)
Android Studio 是 Google 官方推出的免费 Android 应用开发集成环境,基于 IntelliJ IDEA,内置模拟器、调试器、性能分析及 Compose 界面工具,功能全面,文档丰富,是安卓开发首选工具。(239字)
1515 1
|
18天前
|
IDE 开发工具
Qoder 上线 Sonus 模型,Computer Use 能力全面增强
Qoder国际版上线全新内置大模型Sonus(/ˈsoʊnəs/),全球领先,专精超长任务执行与电脑操作(Computer Use)。配合Qoder桌面端0.2.3版本,可自主完成编程、金融建模、科研及表格制作等复杂工作。现全面支持Qoder全系产品,效率提升3.2倍。
1898 9
Qoder 上线 Sonus 模型,Computer Use 能力全面增强