订单主表必须拆分 order
和 order_summary
电商订单量大、查询场景多,把所有字段塞进一张
order表会导致频繁的锁竞争和慢查询。真实生产中,
order表只存核心不可变字段,比如
order_id、
user_id、
status、
created_at;而金额、优惠、运费等易聚合或需频繁统计的字段,应剥离到
order_summary表,用
order_id关联。
这样做有两个实际好处:一是
order表能加更细粒度的索引(比如按
user_id+
status查用户订单),二是避免大字段(如 JSON 格式的优惠明细)拖慢高频查询。
常见错误是把所有字段堆在一张表里,结果一查“用户最近 10 笔订单”,就触发
Using filesort和全表扫描。
order_item
表必须冗余商品快照信息
下单那一刻,商品价格、名称、SKU 编码、库存状态都必须固化进
order_item表,不能只存
product_id后期靠 JOIN 查询。否则商品下架、改名、调价后,历史订单会显示错乱,财务对账直接出问题。
冗余字段至少包括:
product_name、
sku_code、
price_at_order、
quantity、
snapshot_json(存当时规格参数,如颜色/尺码)。
注意:不要用
TEXT存快照 JSON,推荐
JSON类型(MySQL 5.7+),方便后续用
JSON_EXTRACT()查询,也支持生成虚拟列建索引。
状态流转必须用整型枚举 + 状态机日志表
别用字符串存
status字段(如
'paid'、
'shipped'),统一用 tinyint,比如:1=created, 2=paid, 3=confirmed, 4=shipped, 5=completed, 6=canceled。好处是排序快、索引小、不易拼错。
但光靠一个字段不够——你得知道谁在什么时候把订单从“已支付”改成“已发货”。所以必须配一张
order_status_log表,字段包括:
order_id、
from_status、
to_status、
operator_id、
remark、
created_at。
关键点:状态变更必须走事务,先 INSERT 日志,再 UPDATE 主表,防止日志丢失导致状态不可追溯。
分库分表前先做垂直拆分,尤其隔离交易与风控数据
刚起步时别急着 ShardingSphere 或 MyCat 分库,先做垂直切分:把订单核心链路(
order、
order_item、
order_payment)放一个库,把风控规则、用户行为埋点、物流轨迹这些低一致性要求的数据,挪到其他库。
理由很实在:订单库要扛住秒杀写入峰值,而风控数据可以容忍延迟几秒同步;混在一起反而让主库被慢查询拖垮。
容易忽略的是:跨库关联查询(比如“查某用户所有订单 + 对应风控评分”)必须收口到应用层,用两次查询 + 内存 join,别指望 MySQL 联合多个物理库。
真正需要水平分表,通常出现在单表行数超 2000 万、日增订单超 50 万之后,那时再按
user_id或
order_id哈希分片也不迟。
