订单表是电商或交易类系统的核心,设计时要兼顾业务清晰性、数据一致性和查询效率。重点在于分离核心实体(用户、商品、订单)、避免冗余、预留扩展空间。
订单主表:记录订单基本状态和归属
存放订单的全局信息,不存明细,不存价格快照(价格应由订单项承载)。
order_id:主键,建议用 BIGINT 自增 或 UUID(分布式场景优先雪花ID) user_id:关联用户表,NOT NULL,加索引 order_status:如 'pending', 'paid', 'shipped', 'completed', 'cancelled',用 ENUM 或 TINYINT + 注释说明,避免字符串拼写错误 total_amount:订单总金额(元),用 DECIMAL(10,2),不是 FLOAT created_at / updated_at:时间戳,自动维护 pay_time / ship_time:可为空,按需记录关键节点时间订单项表(order_items):拆解每一件购买的商品
一对多关系,一个订单可含多个商品;此处保存下单时的价格、数量、规格快照,确保历史可追溯。
id:主键,自增 order_id:外键,关联订单主表,加索引 product_id:商品ID,可为空(比如虚拟服务类无实物ID),加索引 sku_id:具体规格ID(如颜色+尺寸),更精准,推荐必填 quantity:购买数量,TINYINT 或 SMALLINT 足够 unit_price:下单时单价,DECIMAL(10,2),不可从商品表实时查——价格可能已变 subtotal:小计 = quantity × unit_price,冗余字段,提升统计效率,也可不存(应用层计算)关联与约束:保障数据一致性
MySQL 层面通过外键 + 索引兜底,但业务逻辑仍需在应用层校验。
order_items.order_id 应设 FOREIGN KEY 指向 orders.order_id(启用 InnoDB,且注意外键对批量插入性能的影响) 在 orders 表上为 user_id、order_status、created_at 建复合索引,例如 (user_id, order_status, created_at) 支撑用户订单列表查询 在 order_items 上为 order_id 建索引(必选),为 sku_id 单独建索引(便于按商品查销量) 避免在订单主表里存用户姓名、手机号、地址——应通过 user_id 关联用户表,地址另建 order_addresses 表(支持多次收货不同地址)可选但推荐的扩展结构
初期可简化,但架构上要留出接口,避免后期大改。
order_addresses:独立地址表,字段包括 name、phone、province/city/district、detail、postal_code,关联 order_id order_logs:记录订单状态变更日志(谁、何时、从A到B、原因),用于排查和审计 refunds / returns:退款/退货单独建表,不要直接更新订单主表字段,保证原始订单不可变