SPU主表应存抽象商品的通用属性:spu_id(主键)、brand_id、category_id、spu_name、base_price(基准价)、status(上下架状态);不存price、stock等SKU级字段,避免冗余与更新异常。

商品主表(spu)该存哪些字段?
SPU 是抽象的商品概念,比如“iPhone 15”,它不关心颜色或存储容量。设计时要避免把 SKU 细节塞进来,否则会导致数据冗余和更新异常。
-
id必须是自增主键或 UUID,别用业务编码当主键(比如"iphone15"),后续改名或合并 SPU 会非常痛苦 -
title、description、category_id这类通用信息放这里,但别存price或stock—— 它们属于 SKU 级别 - 建议加
status字段(如"on_sale"/"discontinued"),控制整组 SKU 的上下架,而不是逐个更新 - 如果支持多语言,
title和description不宜直接存在主表,应拆到spu_i18n表,用spu_id + locale联合主键
SKU 表怎么关联属性与库存?
SKU 是可售卖的最小单位,比如“iPhone 15 黑色 256GB”。它必须能精确表达规格组合,并支撑库存、价格、图片等差异化字段。
-
spu_id外键指向商品主表,强制归属关系 - 规格值不建议用 JSON 存(如
{"color": "black", "capacity": "256GB"}),查起来慢、无法索引、难校验。应该建sku_spec_value关联表,结构为:sku_id、spec_id(如“颜色”)、value_id(如“黑色”) -
price、cost_price、stock、weight这些都必须在 SKU 表里,且默认不允许为 NULL;缺货时设stock = 0,别删记录 - 加唯一索引:
UNIQUE KEY—— 实际中可用哈希字段(如uk_spu_id_spec_ids(spu_id, spec_id_1, spec_id_2, ...)spec_hash CHAR(32))替代多个 spec_id 列,写入时计算 MD5,查询快、建索引友好
属性与规格值如何分层建模?
电商常混淆「属性」(Attribute)和「规格」(Specification)。前者用于搜索筛选(如“是否支持防水”),后者用于生成 SKU(如“颜色”“内存”)。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 单独建
attribute表,含name("防水等级")、type("bool" / "text" / "number")、is_spec(布尔值,标记是否参与 SKU 构建) -
spec表只存name("颜色")、sort_order,不存具体值;具体值存在spec_value表,含spec_id、value("黑色")、image_url(可选) - 关键约束:一个
spu只能绑定一组spec,通过spu_spec关联表实现(spu_id + spec_id联合唯一),防止出现“iPhone 15 同时有‘颜色’和‘口味’”这种逻辑错误
为什么不能用 EAV 模型?
有人想用 Entity-Attribute-Value(EAV)动态存各种属性,短期看着灵活,上线后基本都会推倒重来。
- 查询性能差:一次商品详情页可能要 JOIN 5~10 次
entity_attribute_value表,MySQL 优化器容易选错执行计划 - 无法加有效索引:你没法给“所有属性值”建联合索引,搜索“黑色 + 256GB + 有现货”就得全表扫
- 事务难保障:更新一个 SKU 的多个属性值,需要多条 INSERT/UPDATE,出错时回滚复杂
- 更现实的替代:用
JSON字段存非关键、非查询用的扩展信息(如extra_info JSON存“包装清单”),但绝不用它存price、stock或规格组合
实际项目里,最易被忽略的是 spec_hash 的生成逻辑和更新时机——它必须在插入 SKU 时由应用层严格计算,不能靠数据库触发器,否则分库分表后跨节点不一致。还有就是 spu.status 和 sku.status 的语义差异,前端常误以为关掉 SPU 就自动下架所有 SKU,其实得同步更新每个 SKU 的状态,漏掉就变成“商品不可见但链接还能下单”。










