凌晨两点,我被一条慢查询告警叫醒。日志里那条 SQL 跑了 2.7 秒,查的是订单表,单表已经 1.1 亿行。加索引、换 SSD、调 Buffer Pool,这些常规手段我都试过,最多只是把 2.7 秒压到 1.8 秒,治标不治本。真正让我下定决心用 ShardingSphere 做分库分表的,不是某一个技术指标,而是我意识到单表模型在数据量继续增长的情况下,已经没有“优化”空间了。
这篇文章会把我从“要不要拆”到“怎么拆”,再到“拆完上线踩了哪些坑”的完整过程写出来。适合手里已经有单表数据量过千万、正在犹豫是否要分库分表的团队,也适合已经决定引入 ShardingSphere 但不知道从哪下手的同学参考。我会把配置、分片算法、数据迁移、分布式事务、连接池这些容易翻车的点都讲清楚。
1. 订单表冲到 1.1 亿行之后,我做的第一件事不是换硬件,而是先看清瓶颈
1.1 那两条慢 SQL,让我意识到索引救不回来了
我们的订单表结构不算复杂,核心字段就是订单 ID、用户 ID、订单状态、下单时间、支付金额、商品快照 JSON 等。早期每天几十万单的时候,这条表非常老实,主键查询都是毫秒级。等日订单量爬到百万级,问题就来了。
业务方最常跑的查询有两个:
sql复制SELECT * FROM t_order WHERE user_id = ? ORDER BY create_time DESC LIMIT 20;
SELECT * FROM t_order WHERE order_status = 0 AND create_time BETWEEN ? AND ? ORDER BY create_time DESC;
第一个查询,我们加了 (user_id, create_time) 联合索引,前期效果不错。第二个查询,也加了 (order_status, create_time) 的索引。但等表数据量超过 8000 万以后,这两个索引的维护成本越来越高,B+ 树层级从三层往四层爬,写入时的页分裂也频繁出现,最直观的感受就是:慢查询数量开始线性上升,DBA 每周都要处理一次索引碎片。
我当时的判断是:单表接近 1 亿行以后,数据
