商品表核心字段包括:goods_id(bigint unsigned主键)、sku(唯一非空字段,用于订单和仓配对账)、price与market_price分离存储、status用tinyint(1)存状态码;不存库存、不冗余展示字段,确保支撑订单、库存、搜索、促销等业务逻辑。

商品表要存哪些字段,而不是“怎么漂亮”
商品表不是用来展示的,是给订单、库存、搜索、促销逻辑提供准确数据的。核心矛盾在于:字段太少,后续加活动、规格、多仓库就崩;字段太多,日常查 SELECT * 拖慢首页。
-
goods_id必须是主键且用BIGINT UNSIGNED,别用INT——中大型电商半年就超 2147 万条 -
sku字段必须存在且唯一(不是主键),它是订单关联和仓配系统的事实主键,别指望靠goods_id去对账 -
price和market_price分开存,促销时只改price,前端展示逻辑才不会错乱 - 别在商品表里存库存数量——
stock属于 SKU 级别,必须拆到goods_sku表,否则多规格商品(如颜色+尺寸)根本没法算 -
status用 tinyint(1) 存状态码(如 1=上架, 2=下架, 3=审核中),别用字符串,避免WHERE status = 'on_sale'这种低效查询
订单主表和明细表为什么不能合在一起
合表看着省事,上线三个月后就会遇到两个硬伤:一是订单导出慢(JOIN 商品表 + 分类表 + 用户地址表),二是无法做订单快照——商品改价或下架后,历史订单金额就对不上。
- 订单主表
order只存全局信息:order_no(唯一索引)、user_id、total_amount、status、created_at - 订单明细表
order_item必须包含当时快照:goods_name、sku_code、price、quantity、spec_info(JSON 字段,存“黑色/L”这类文本,不关联规格表) -
order_item.goods_id和order_item.sku_id都要保留,前者用于统计销量,后者用于仓配拣货 - 别给
order_item加外键约束——高并发下单时,InnoDB 的外键检查会成为性能瓶颈
为什么订单状态变更不能只靠 status 字段加数字
只用一个 status 字段存 1/2/3/4,会导致无法回溯“谁在什么时候把订单从待付款改成已发货”,也撑不住售后流程(比如“已发货→申请退货→退货中→已退款”这种分支)。
- 必须建独立的状态流转表
order_status_log,字段至少含:order_id、from_status、to_status、operator_type('user'/'admin'/'system')、created_at - 每次状态变更都 INSERT 一条日志,而不是 UPDATE 主表
status——这样查纠纷单时才能明确责任节点 -
order.status字段只存当前值,用于列表页快速筛选;所有业务判断(如“能否取消”)必须查最新一条order_status_log记录,而不是直接读order.status
MySQL 引擎、索引和字符集这些细节真会出事
开发阶段调通就行,上线后第一条慢查询往往就卡在这几个地方。
- 所有表必须用
InnoDB,别用MyISAM——事务、行锁、外键支持缺一不可,尤其订单支付回调必须事务保证 -
order_no字段建唯一索引,但别设为PRIMARY KEY(主键还是用自增id),否则分库分表时迁移成本爆炸 - 商品搜索常用字段(如
name、category_id)要联合建索引,例如INDEX idx_cat_status (category_id, status),别指望单列索引扛住并发筛选 - 全部表用
utf8mb4字符集,否则用户收货地址里存个 ? 或 emoji 就报错;collation统一用utf8mb4_unicode_ci,避免大小写比较出问题
字段命名看着琐碎,但每一条都是线上查慢日志、对账不平、客服投诉后补出来的。真正麻烦的不是设计,是改表结构——一旦订单表有千万级数据,ALTER TABLE 就得停机两小时。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











