1. 单表还扛得住的时候,我把分库分表想简单了
做淘客系统的后端,最难受的往往不是业务方今天又提了什么花式需求,而是推广订单表在单库里一天天膨胀,慢查询越来越多,DBA监控面板像心跳监护仪一样在报警。数据库分库分表这件事,网上文档一大把,可真落到“用户 ID 与时间维度双策略 Sharding”上,踩过的坑比想象中多得多。我最早也以为分库分表就是把一张大表按某个字段劈成多份,但真正设计时第一道坎就来了:按用户 ID 切分,用户侧查询很顺;按时间切分,归档和统计很顺;两个维度都不舍得丢,怎么把它们叠在同一套规则里才不打架?
当时手上的核心表是一张推广订单流水表,每条记录代表一次电商平台成交回传,关联着推广者、订单号、商品、渠道、预估佣金、结算状态。淘客业务有个非常明显的特征:数据是纯流水型的,只增不减,而且每一次成交都会触发至少一轮回传写入。推广订单一旦产生,订单状态还会变化,比如用户退款、佣金失效,这意味着同一笔订单会被 update 多次。起初单表几百万行时,所有查询都很快;等到数据爬到三千万行左右,问题开始浮出水面。
1.1 先还原一张推广订单表的真实压力
我当时面临的表字段并不复杂,核心字段大概是:推广者 ID、商品 ID、平台订单号、成交金额、佣金、订单状态、下单时间、回传时间、结算月份。为了支持推广者后台的“我的订单”“团队业绩”“月度账单”页面,索引建得很重,比如 (promoter_id, create_time)、(platform_order_id)、(order_status, settle_month)。索引多建一个,写入链路就多一份负担,订单回传高峰的时候,InnoDB 的写盘和 binlog 同步压力已经让主库 CPU 吃紧。
真正压垮单表的是一类典型的运营查询:
sql复制SELECT order_no, item_title, pay_amount, commission_amount,
order_status, create_time, settled_time
FROM t_promoter_order
WHERE promoter_id = 102381
AND create_time >= '2024-01-01'
ORDER BY create_time D
